Earlier quoted context omitted.
Immutability probably does simplify a lot of things; but it isn't actually required to get Erlang's model, since Erlang isolates the state of processes from each other. Each process could have its own isolated mutable state as opposed to an immutable one and it wouldn't change the "let it crash" philosophy.
You can't guarantee that isolation without immutabilty, or at least forced copying. In Go, it's extremely easy to accidentally send a pointer (or a data structure that contains a deeply nested pointer somewhere; this includes embedded maps, slices and channels, which are all reference types) on a channel, which is bound to break mutability guarantees at some point.
Comparing Elixir and Go
181–190 of 202 posts
Re: Comparing Elixir and Go
#182Earlier quoted context omitted.
You can't guarantee that isolation without immutabilty, or at least forced copying. In Go, it's extremely easy to accidentally send a pointer (or a data structure that contains a deeply nested pointer somewhere; this includes embedded maps, slices and channels, which are all reference types) on a channel, which is bound to break mutability guarantees at some point.
Mutable locals do not necessarily imply pointers...
If you pass a "local" on a channel to a different goroutine, Go can't guarantee to the receiver (which now has it as a "local" variable) that the sender (which still has it as a "local") won't change it:
d := map[string]int{}
ch
The only way to do this safely is to to write a channel abstraction which uses gob or similar to marshal and unmarshal all data, thus copying it and preventing concurrent mutation, and then always use the channel abstraction. But always copying tends to be terrible for performance. Erlang is able to do zero-copy sends to process mailboxes because the data is guaranteed to be immutable.Sure, you could instead mandate that senders never hold on to data sent on channels, but can you ensure this 100% across a codebase contributed to by an entire team?
Re: Comparing Elixir and Go
#183I still don't understand what all the hype is about pure functional programming. Sometimes mutations are useful. There are lot of good programming design patterns which depend on mutations. Also, always copying objects by value every time you call a function seems very expensive; especially if you're dealing with very large objects/structs/maps/strings which have to be processed by many functions.
It's just easier to think of a pure functional construct, there's less possibility for mistake.
No one claims it to be efficient at single operations. Though some people blame the hardware for that, as in theory, there's nothing slower about it.
Re: Comparing Elixir and Go
#184Author here. This was published a week earlier than expected so just a heads up that there are a couple of edits coming.
A quick question, you talk about Elixir yet mention Erlang a lot. Is the choice of Elixir over Erlang purely syntactic preferences? Or is Elixir just an all around win above Erlang?
Re: Comparing Elixir and Go
#185Earlier quoted context omitted.
Mutable locals do not necessarily imply pointers...
No, but how do you pass "mutable locals" to other processes? That's the whole question. If you pass a "local" on a channel to a different goroutine, Go can't guarantee to the receiver (which now has it as a "local" variable) that the sender (which still has it as a "local") won't change it: d := map[string]int{} ch The only way to do this safely is to to write a channel abstraction which uses gob or similar to marsha…
Isn't that precisely what Rust is all about?
Re: Comparing Elixir and Go
#186Earlier quoted context omitted.
No, but how do you pass "mutable locals" to other processes? That's the whole question. If you pass a "local" on a channel to a different goroutine, Go can't guarantee to the receiver (which now has it as a "local" variable) that the sender (which still has it as a "local") won't change it: d := map[string]int{} ch The only way to do this safely is to to write a channel abstraction which uses gob or similar to marsha…
> Sure, you could instead mandate that senders never hold on to data sent on channels, but can you ensure this 100% across a codebase contributed to by an entire team? Isn't that precisely what Rust is all about?
Re: Comparing Elixir and Go
#187Author here. This was published a week earlier than expected so just a heads up that there are a couple of edits coming.
Great comparison. I'd love to see this expands to more languages. A quick question, you talk about Elixir yet mention Erlang a lot. Is the choice of Elixir over Erlang purely syntactic preferences? Or is Elixir just an all around win above Erlang?
Erlang, with its small and hard to extend syntax, its libraries, frameworks, and conventions, is geared towards stability. Erlang is meant for creating reliable systems, which will be maintained for decades. Erlang is the most conservative (in the sense Steve Yegge's post) of dynamic languages out there: it's verbose, predictable, boring, consistent, reliable and focused solely on fault-tolerance (ie. long term stability).
Elixir tries to be a less conservative Erlang, but also good enough scripting and general purpose programming language. It's not a drastic change in capabilities, but rather re-focusing the language a bit to be more friendly to abstraction and extension. Elixir delivers on its promises magnificently: for my latest project, where I need the most expressive language I can get, I considered Elixir among such languages as Smalltalk, Io, Common Lisp, and Lua.
So it's more than just syntactic preferences, but the two languages remain very closely related. Elixir functions are Erlang functions, you can use Elixir modules from Erlang just fine and so on. Erlang is a simpler language, so my advice is to start learning Elixir and you'll learn Erlang when reading articles about its libraries that you want to use.
Re: Comparing Elixir and Go
#188Earlier quoted context omitted.
Sure, but I don't know any pure languages that provide no facilities for mutation whatsoever, they just ask you to be explicit about it and add some syntactic weight (which is a good thing, you want mutation called out as a reader). Haskell provides several different mutation options from simple references to various kinds of thread-safe references depending on what semantics you need. There's even a "no-really-trust…
Erlang is purely immutable and doesn't have any "facilities for mutation" that I know about, although it does have side effects (I/O, but no Haskell-style effect system).
Re: Comparing Elixir and Go
#189Earlier quoted context omitted.
Sure, but I don't know any pure languages that provide no facilities for mutation whatsoever, they just ask you to be explicit about it and add some syntactic weight (which is a good thing, you want mutation called out as a reader). Haskell provides several different mutation options from simple references to various kinds of thread-safe references depending on what semantics you need. There's even a "no-really-trust…
Erlang is purely immutable and doesn't have any "facilities for mutation" that I know about, although it does have side effects (I/O, but no Haskell-style effect system).
Sadly the place where I worked was not keen on open source posture, so it's locked away for all of time probably. However, the place I now work is a lot more open source friendly and I expect to take another whack at it, but using Rust on the NIF side this time around instead of C.
Re: Comparing Elixir and Go
#190Earlier quoted context omitted.
If a rogue cosmic ray flips a bit in a running process handling phone calls (note: this exact thing apparently took down all of Amazon S3 once, http://status.aws.amazon.com/s3-20080720.html ), in code that wasn't expected to error, 1) Go will crash or at minimum (arguably much worse) go into an unknown state. 2) C++ will crash, and ideally, restart, but lose all "live" state. (So calls get dropped, etc.) 3) Erlang/El…
I'm not sure if you're being serious, but a random bit flip can easily put a process in an incorrect state rather than make it crash (say charge a user $1000000 instead of $1), or affect a pointer (of which Erlang uses a ton internally - imagine for a second how lists, maps, and code loading work) and make the whole VM crash when it tries to access it. Or it could just kill the OS itself. You would have to be incredi…