3 ms·
I work in Elixir most of the time but can read and write Erlang reasonably well, here's my two cents. Elixir's syntax was inspired by ruby and so if you've use
by ihumanable 6y ago
I work in Elixir most of the time but can read and write Erlang reasonably well, here's my two cents.
Elixir's syntax was inspired by ruby and so if you've used ruby or look at ruby code and think, "yea, I get what's going on here" then you will likely find working with Elixir's syntax preferable to Erlang. Erlang's syntax was based off of Prolog and so it will be less familiar, unless you have done a bunch of Prolog programming.
Elixir layers on a bunch of things that are very nice to have at a language level, the ability to rebind names is probably the one that most impacts code. In Erlang you can't rebind a variable, so Erlang code ends up either using lots of very small functions of having variables like `n` `n2` `n3`. It's not that you can't write good, clean, easy to reason about code in Erlang, but if you are coming from a language with mutability and variable rebinding, it's a bit of a culture shock. I find that Elixir hits a nice medium ground to allow you to wrap your head around immutable data structures, functional programming, actor model, OTP without ALSO having to climb the hills of unfamiliar syntax and some limitations (like variable rebinding) that aren't strictly necessary.
From a tooling standpoint, I find Elixir to be a bit more pleasant than Erlang. Mix (build tool) is great, ExUnit (unit testing) is great, ExDocs (docs generation) is great, Hex (package management) is great. The Elixir community has somehow stayed pretty unified when it comes to tools and for the most part they work really well.
From an interoperability standpoint, you really don't leave anything behind choosing to use Elixir over Erlang. Erlang dependencies work just fine, and the interop is so easy, here, I'll give you an example.
Want to use an Erlang module directly from your Elixir code, here's an example of how to use the timer module.
:timer.seconds(1)
That's it, that's the interop, you don't have to import anything weird, you don't have to fence off your code, you don't have to juggle types from Elixir types into Erlang types and back again. Want your Erlang interop to look more like elixir, two lines of code.
alias :timer, as: Timer
Timer.seconds(1)
Overall the Erlang and Elixir communities are friends (and Gleam, LFE, and all the other BEAM Languages). It's a very positive community all working to build great functionality on top of the really cool piece of tech that is the BEAM VM.
- PopeDotNinja 6y agoSpeaking for myseld, rebinding variables in Elixir is my least favorite part of the language, and I specifically avoid using the feature.
- ihumanable 6y agoYea, I'm mostly approaching this from the point of view of learning any new language is climbing a learning curve. If you are coming from most of the mainstream languages (java, javascript, python, etc) you are going to want to rebind things because that's how imperative languages roll. This is probably colored from my own experience of going from Python (mainly) to Elixir (mainly). As a toy example, imagine having to remove all the negative numbers from a list in the middle of a function. Most python programmers would reach for a list comprehension after learning about list comprehensions (which is great because they are more FP) my_list = [number for number in my_list if number >= 0] So you pick up Elixir and you are trying to do the equivalent thing after reading through the docs my_list = for number <- my_list, number >= 0, do: number And that works fine, it's my_list is exactly what you expect, no negative numbers. Let's try the same thing in Erlang MyList = [X || X <- MyList, X >= 0]. ** exception error: no match of right hand side value As a new user coming to the language, trying to do something so simple and getting a somewhat opaque error message is a significant degree of friction. I have found that when I want the old value of a variable to no longer be available rebinding the name is a great way to ensure that. If in the future I decide that I need the old value later on in the function I can always just change the bind to some other name easily enough, but it prevents me from using state when I meant to use updated_state. Not to say one way is better than the other, I just found this use of rebinding to work well for me by making it "impossible" to use the old / stale / out-of-date value.
- dnautics 6y agoyou shouldn't do it in your code, and code linters (well, credo) can check for it and yell at you. I think you might have to activate it currently. I 100% guarantee you don't miss "immutable variables" in your REPL. Pid = module:start_link(...). oh crap. start_link/n returns {:ok, _}, not naked pid. {ok, PidForRealThisTime} = Pid.
- sodapopcan 6y agoI'm on the fence about re-binding variables. I don't really mind it and have gotten used to the pin operator when I need it. I actually use variable re-binding quite a bit but always only in situations where I want a prime. def foo(bar) do bar = decorate(bar) {:ok, bar} end I like that better than calling it something like `new_bar`. I kind of wish there was prime syntax along the lines of `bar' = decorate(bar)` but I can deal with re-binding when only used like this (and really, the stakes are low). More complex cases can generally always be handled with piping.