9 ms·
Elixir 1.2.0 Released
- quaunaut 11y agoHow ironic, I was wondering just last night when 1.2 would be released. I'm a newcomer to Elixir, and have really been enjoying it. As a Python->Rubyist, it's been really interesting to finally hit a functional language, and some of Elixir's most basic features just seem crazy in comparison to what I've come from. Some neat examples: * Pattern Matching. In other words- you don't assign things to variables, you match things. Elixir/Erlang is just doing algebra behind the scenes. I'm sure this is a gross simplification, but it's enabled me to write some really condensed code that still makes a bunch of sense. * Streams. I know Node developers would laugh at this being a new concept, but I hit Streams when I was doing Node, and I didn't get it. Streams in Elixir feel much more self-evident, and feel much easier to read. * The Pipe Operator( |> ). This effectively lets you simplify code by just passing results from one thing to the next. For example(taken from the excellent "Programming Elixir" by Dave Thomas): $ (1..10) |> Enum.map(&(&1*&1)) |> Enum.filter(&(&1 < 40)) => [1, 4, 9, 16, 25, 36] So there, it takes the 1..10 range, maps the squares of each element to an array, then filters the array to just the elements that are less than 40. It's a surprisingly enjoyable language to program in, and best of all coming from a Rubyist- the performance gains are automatic, especially once you grok some of Elixir's crazier(but easy to understand) powers. ----- The other thing I really like about it, is how friendly the community seems. I feel personally predisposed toward extremely friendly communities- Ember.js was the first community that made me feel like I had a home- and the care with which Jose Valim and the core team treat people, and the general "Give back everything you can" attitude of the community is really just inspiring. My newest side project was something I dropped because I thought that the hardware necessary would make it not worth the effort of building it, but now I have complete confidence in it. I encourage you to take a shot at it if you're looking for a fast, functional language with a clear syntax and easymode concurrency.
- Cyph0n 11y agoI hear Elixir is great, but I understood and still enjoy what you described in Scala, so I don't see what makes it unique. On top of this, it runs on the JVM, so you get to use the entire history of Java libraries whenever you need it. Your example: >> (1 to 10).map((x) => x*x).filter(_ < 40) Of course, Scala is an extremely complex language, but I just take the features I feel are useful and/or relevant to what I'm trying to accomplish. Another up and coming JVM language with similar capabilities to Scala is Kotlin. If it can take off on Android, I think it will become quite popular.
- quaunaut 11y agoWith Elixir, you can use Erlang libraries(or just plain Erlang) right inside of it, very similar to what you describe with Scala! I've never used Scala personally, and my Java programming was all school-related, so sadly I just don't have the relevant knowledge to explain the differences.
- aczerepinski 11y agohttps://medium.com/this-is-not-a-monad-tutorial/interview-with-jesper-louis-andersen-about-erlang-haskell-ocaml-go-idris-the-jvm-software-and-5628fe591295#.tp0q127cn https://medium.com/this-is-not-a-monad-tutorial/interview-wi... That link mentions some of the tradeoffs that Elixir and Scala would have just due to the VMs they run on.
- Cyph0n 11y agoThanks for that! The explanation is concise yet easy to understand.
- lostcolony 11y agoThe functional aspects are not really that different. I think the key one is that Erlang has tail call optimization baked in, whereas Scala achieves something close, but not exactly there, by working around the JVM's limitations. Scala's implementation works really well when you have a function calling itself, or two functions mutually calling each other, and that basically supports recursion. But the inability of arbitrary function A -> arbitrary function B -> C -> D, etc, to be used, without risking blowing the stack, does lead to some very simple, easy to understand patterns for control to be unavailable (see Scala actors 'become' below). From what experience I have (played with Scala, done real dev work in Erlang) - The lack of inheritance in Erlang/Elixir is a difference. It's one I like (and from what I've seen, the more a person uses Scala the less inheritance they end up using), but others may not. Actors behave similarly between the platforms, but have a few differences. Whereas in Scala actors (by this I mean Akka) struck me as reactive, in Erlang they struck me as proactive. What I mean is that Scala, at least when I looked at it, it seemed like you create an actor system, and then actors in it, and they do nothing until you send a message. In Erlang, you just create a new process and at any time it can pause to receive a message. That is, the 'actor' is just a thing that does work and has a mailbox, rather than this reactive interconnection of things. Fundamentally there may not be much difference, but I found the abstraction in Erlang easy to initially grok, and playing with Scala led me to some irritation and difficulty in structuring my program. That may have been just due to my own expectations rather than anything innate, but just pointing out, they are a bit different. Scala actors also have the idea of 'become' when you want to change an actor's behavior (and in general the behavior of an actor feels more rigid to me). In Erlang, an actor is just a process running whatever code. Between that and tail call optimization, the idea of 'become' doesn't exist; if at the end of the function that is executing in the actor's process I want to perform the same action I just recurse; if I want to perform a different action I call a different function. That makes for a very simple mental model to work from; I start an actor and it immediately starts executing (though that execution might just be "wait for a message"), and it runs pretty predictably until either it gets "wait for a message", hits the end of a function (in which case it terminates cleanly), or dies. If you want it to run the same logic more than once you recurse, if you want it to run different logic you call a different function. So the 'actor' part is nothing special, no hand waving or magic, it just is a single process with a mailbox you can check, and I find that delightful to reason about; in Scala actors felt like special ~things~, that I have to configure and then set off. Performance is a difference; while the JVM is more performant in just sheer number crunching, Erlang has a memory model that better fits actors; there is no stop the world garbage collection. In general, barring something like Azul (which I have no experience with), you'll see a smaller deviation of latencies in Erlang (useful for web servers and things, where every call taking ~5ms is better than having some calls return in 1ms, and others in 120ms). Scala borrowed a lot of the distribution and fault tolerance mechanisms from Erlang, but I don't like them as much. They feel a bit more bolted on, and the multi-paradigm mixing means a greater degree of rigor is required to ensure you do things properly. That said, Scala seemed to provide a different level of abstractions for supervision strategies, that I didn't really delve into. The availability of all the JVM libraries is a double edged sword for Scala; while there probably is a JVM library for whatever you want to do, it also probably behaves in ways that won't play nice with your actors, possibly forcing you to deal with multiple concurrency, distribution, and fault tolerance models simultaneously. In Erlang (in which, I might add, I've found libraries for basically everything I wanted to do, that wasn't something extremely esoteric like talk to a piece of hardware that is only used in (X) business domain...of which there was also no Java bindings, only C), unless it's calling out to external code (NIFs and the like), it will at least be informed by the concurrency model you're using (since Erlang it's actors or nothing), though there may be assumptions and expectations and such that the library makes that you will need to understand or modify.This generalizes to the language as a whole, too; in Scala it's very easy to make tradeoffs that will end up hurting you. In fact, it's practically encouraged, as the language is often sold as a way to slowly move into a more functional, safely concurrent world. The problem I have with that is without being forced to move, a lot of devs won't, and mixing paradigms gets you complexity that is usually unnecessary, and oftentimes leads to you not seeing the benefits you'd have gotten had you limited yourself to one. Another fault tolerance difference (that won't affect you 99% of the time) is that Erlang has better process isolation. An uncaught exception in one process won't affect another one, unless they've been linked together or otherwise been entwined such that they should cause the other to crash. Scala tries to do the same, and largely succeeds, but it doesn't have the same technical underpinnings due to the nature of the JVM. The profiling/tracing ability of the Erlang VM is better than the JVM (yes, really). The ability to attach a remote shell to poke and prod your running instance is also flat out amazing; I don't recall if Scala had anything similar. I always found Erlang apps to have a fairly small footprint on my box, whereas my experience with the JVM (though mostly using Java) saw them tending to take a fair amount of resources.
- jacquesm 11y ago> I know Node developers would laugh at this being a new concept I hope you're not somehow implying that node developers came up with this concept.
- quaunaut 11y agoAh, that wasn't my intention! Just, the Node community is probably the closest to the Ruby/Python crowd in terms of overlap, and what I assume might be reading a post from a developer like myself.
- jacquesm 11y agoThanks for the clarification. I figured better to ask you than to hit the 'downvote' button without verification. Happy 2016 :)
- gotchange 11y ago$ (1..10) |> Enum.map(&(&1**&1)) |> Enum.filter(&(&1 < 40)) This is the equivalent of this piping op done in terse style JS: [for (i of Array(10).keys()) ++i].map(e=> e*e ).filter(e=> e<40 ) This is not as concise as the example you provided but it's still very neat and powerful.
- oinksoft 11y agoAre list comprehensions still part of ES7? It's strange that Babel removed the list comprehension transformer recently, but I haven't been following closely. The Elixir pipe syntax is reminiscent of Clojure's ->/->>: (->> (range 1 10) (map #(* % %)) (filter (partial > 40))) It's nice that in languages like Haskell or ML this is trivial: infix |> fun (a |> b) = a b You could modify this to let NONE fall through, etc.
- Spiritus 11y agoNot knowing Elixir at all, what's with all the & operators in your pipe example? Looks very unappealing to me.
- Bockit 11y agoIt's the super terse anonymous function syntax. You could use the slightly more verbose version with named instead of positional params or put a named function in there instead.
- jeremyjh 11y agoThis is a shorthand for writing anonymous functions. The &() activates the feature for the expression inside, which can then use &1, &2 etc to apply parameters. For example `&(&1 + 1)` is equivalent to `fn x -> x + 1 end` .
- deleted 11y ago[deleted]
- lectrick 11y agoIt's a shorthand. Once you get tired of the long form, the shorthand will be appealing :P
- dwoot 11y agoWe call it the "capture" operator. What it does is it captures the nth parameter of the anonymous function. Like some have already said, the number just signifies which parameter you're making a reference to in the function body. It's terse and comes in handy for ad-hoc stuff. I prefer verbosity and often write Elixir code with the standard syntax and find myself using the capture operator a lot more in the REPL.
- lobster_johnson 11y agoIt's also worth mentioning that the Node community took a long time to get streams right, and "Streams 2.0" is still poorly documented. For example, a major feature of the redesign is backpressure support, but it's not at all obvious how it's supposed to work, and there are no mechanisms available in the standard library to tweak it. Streams also still have odd issues you would not expect in a mature release. (Error propagation, for example, is quite broken in practice; if you string together a series of pipe() operations, emitted errors won't propagate up the chain properly.) I haven't looked very closely at Elixir's streams, but the fact that they are based on lazy function evaluation makes them inherently better than what Node.js offers.
- dv_says 11y agoUsing Elixir here for a couple of months, for an app backend, and even for shell script type of projects. Great language, no surprises, and very responsive community -- really, my biggest wish is for more people to try it, as I think it's still relatively niche. Had no previous Erlang experience. While you don't have to write Erlang code itself, you'll over time become familiar with Erlang/OTP architecture concepts, such as GenServer, ETS, distributed nodes, and so on. Was very happy to see this recent post from Pinterest [1] as a sign that some of the more "mainstream" teams are starting to look at it. Also, a repost [2] of some helpful tips if you're just getting started. [1] https://engineering.pinterest.com/blog/introducing-new-open-source-tools-elixir-community https://engineering.pinterest.com/blog/introducing-new-open-... [2] https://news.ycombinator.com/item?id=10278870 https://news.ycombinator.com/item?id=10278870
- jbeja 11y agoSince elixir is base on Erlang, it would have the same Repl workflow that you would find in Clojure?
- nazgob 11y agoClojure runs on JVM.
- ane 11y agoIt does indeed. The interactive shell is called IEx: http://elixir-lang.org/docs/master/iex/IEx.html http://elixir-lang.org/docs/master/iex/IEx.html
- siscia 11y agoAlmost, you definitely have a nice REPL however I find the workflow of Clojure way better. The problem I think lays on the fact that Clojure group function inside very flexible namespace, while Elixir use more rigid modules. However in my limited experience the way you code Elixir feels very different from the way you code Clojure. It's difficult to explain, but I would say that I follow more my gut while I code Clojure and more reflexive while I code Elixir, the code in Clojure support concurrency and parallelism, while in elixir concurrency is the norm... Not sure if I was able to explain it... Both wonderful languages anyway.
- iso8859-1 11y ago> the code in Clojure support concurrency and parallelism, while in elixir concurrency is the norm This makes little sense to me. You feel it is the norm in both? If you are unsure if a post is readable, why not just rewrite it?
- simoncion 11y ago> If you are unsure if a post is readable, why not just rewrite it? One can grapple with several ways to express something, and be unsure which one is the best. Sometimes just publishing is better than being forever stuck in an indecision loop. :) The questions that arise from the confusion can tell you how to better structure your words.
- frik 11y agoCan someone recommend me a community/forum that centers around Elixir? (for Elixir/Erlang beginner)
- nicksergeant 11y agoThe Slack community is very active: https://elixir-slackin.herokuapp.com/ https://elixir-slackin.herokuapp.com/
- frik 11y agoI would favor a forum/board with topics over an chat (IRC/slack - very time consuming). As a last resort I could also use their mailing list.
- djKianoosh 11y agobesides irc/slack it seems what you're lookinn for is a combo of stackoverflow and the google group. I think agree with you though, there's something missing without an organized forum/board, not elixir specific, just overall in our lives ;)
- aczerepinski 11y agohttps://www.reddit.com/r/elixir https://www.reddit.com/r/elixir https://groups.google.com/forum/m/#!forum/elixir-lang-talk https://groups.google.com/forum/m/#!forum/elixir-lang-talk
- imranismail 11y ago> Support for variables in map keys Been waiting for this. To those that have not tried Elixir. I urge you to try it, it's a fun experience
- desireco42 11y agoThis is the best New Years gift I could hope for! :) I've been using and slowly switching towards Elixir for last few months. It is fun, refreshing, enjoyable to work with and community is very welcoming and pleasure to be part of.
- desireco42 11y agoHaving said all this, still enjoy Ruby as much as always.
- lectrick 11y agoJust want to chime in reiterating everyone's thoughts already here that this language is fun, interesting, and worth your time investment to investigate. The biggest hurdles I had coming from OO Ruby were 1) how to handle state, since you no longer can just hang information off any arbitrary object attributes, 2) pattern matching (but now that I grok it, I love it, it's so useful and leads to more concise code), 3) lack of inheritance (although oddly, I don't seem to miss it, it just leads to a somewhat different code design), 4) OTP semantics (which after you mount the learning curve, make a lot of sense from a resiliency standpoint). There are a number of neat little details not yet mentioned or emphasized here such as full Unicode support, full-fledged macros that give you full AST access (in a non-homoiconic language, that is a rarity!), custom sigils (http://elixir-lang.org/getting-started/sigils.html http://elixir-lang.org/getting-started/sigils.html), the ability to easily call into any Erlang library, the fantastic :observer.start() utility for visually observing tons of details about a running pid hierarchy, etc. One possible hurdle unique to languages that feature message passing between independent processes (pids or process id's) as a core feature is that once you have a pid hierarchy, it seems to me that inevitably, one of them will get a backlog of messages requiring you to either apply back-pressure techniques (slowing down upstream synchronous messaging by slowing down replies, basically) or pursue some other strategy (code refactoring etc.) when messages start to get discarded under load due to overflowing the pid inbox.
- simoncion 11y ago> the fantastic :observer.start() utility for visually observing tons of details about a running pid hierarchy, etc. observer is a rather nice tool. It is, -however- not an Elixir feature, but is something that ships with Erlang. [0] As you mentioned, you can call any Erlang code in Elixir (and vice-versa!). IIRC, you do the former by prefacing the Erlang code with a ":". So, ":observer.start()" would be written in Erlang as "observer:start()" and do exactly the same thing. :) [0] Not that you claimed that observer was an Elixir invention, mind. The whole point of this comment is to point out how easy Erlang <--> Elixir interop is. :)
- lectrick 11y agoYes to all of the above :)
- troyk 11y agoWow, already home brewed too! (OSX users can upgrade with `brew update && brew upgrade elixir` and it just magically works -- because awesome people have made it so) What a great way to ring the new year! Happy New Year everyone!
- innocentoldguy 11y agoYou might want to try kiex? It is similar to Ruby's rvm or Node's nvm for Elixir. https://github.com/taylor/kiex https://github.com/taylor/kiex
- szx 11y agoI'd be curious to hear some criticism, negative experiences, downsides from people with deeper experience. This thread is 100% positivity and praise, which is highly unusual for HN (New Year's afterglow??) To be clear, my occasional dabbling in Elixir has yet to reveal any major shortcomings so this isn't an elephant in the room kind of situation, just a genuine request from people whose thoughtful opinions I generally appreciate.
- clessg 11y agoElixir usually receives this much praise, so it's not unusual. Elixir (and Phoenix) are really great. Phoenix is probably my favorite backend framework I've ever used - and I've used a lot. And the community is wonderful. Now, before I sound too much like Trump, there are some downsides, as always. It is a dynamic language, which can be a downside for some. (Type-checking is possible though.) It's not that fast with pure number-crunching, so it's best for distributed, networked applications. The syntax isn't always quite as nice as Ruby. And the language is relatively complex (more than Go, much less than Ruby/PHP/Scala).
- elteto 11y agoFrom my experience the positivity is not unwarranted, Elixir is a great, young language with an awesome community (as most new languages have). The creator, Jose Valim, comes across as a very nice person and I feel that a lot of the positive attitude in the community stems from this. As to the language itself, it feels well designed and fun to use (the pipe operator is really cool). Plus it runs on the Erlang VM which is an incredible piece of engineering. Overall a great next language to pick up and experiment with, plus it has reached a good level of maturity so you won't see your code break from one release to another.
- im_down_w_otp 11y agoI write both Erlang and Elixir. One negative thing I'll say about Elixir is that it sometimes feels like a Ruby-shaped DSL obfuscating the Erlang I would otherwise be writing more clearly. I don't like optional syntax. Like dropping parens for argument lists, etc. Elixir adapted this quality of having varieties of optional syntax from Ruby-land, and I think it makes things harder to read and writing is sometimes ambiguous. So for my part I just avoid it and write out the explicit form every time. I also think the weird variable rebinding doesn't really solve an interesting problem, but also ends up sometimes making things more confusing when reading code in projects written by people who leverage it all the time. I happen to like explicitly naming reused constructs with different names each time they're bound. 1) it makes is explicit which version of a thing you're working with (e.g. Time1, Time2, etc.), and 2) it makes writing the code a lot more similar to how one might sketch up a more formal construction (e.g. T, T', etc.). So here again I just write out the explicit form like I would have in Erlang. To me the very existence of the "pin operator" is kind of an indicator that rebinding was a weird design choice to solve what seems like a non-problem. Lastly there's a fair bit of boilerplate in Erlang when using the OTP patterns, and in Elixir there are often metaprogramming constructs that attempt to provide some sugar or some shortcuts to mitigate that, but I find this is really hard for newcomers when trying to understand how something like say Supervisors work, because in Erlang everything that's going on is explicit and well documented, but in Elixir the connections and relationships between concepts, callbacks, etc. isn't quite as clearly spelled out and the docs don't really help much (in fact they make it more confusing because at the same time they introduce Supervisors they also introduce GenServers, and give the false impression those concepts are tightly coupled). I often point learners at the Erlang docs and give some instruction around OTP concepts in Erlang so that they have an easier time mapping them in Elixir. That said there are a ton of things I really like about Elixir. Starting with Mix. Oh my god how I love Mix. Having the language come bundled with an easy to use build, dependency, and release management tool is unbelievably nice. I also really like the fact that a lot of effort went into organizing the standard library so it's coherent. For the most part things are pretty discoverable. Functions that take state or context to modify pretty much always have it passed in in the same location in the argument list. Whereas in Erlang it's different depending on which module you're in, and sometimes not even consistent inside that same module. Also it's nearly impossible to know where to go look for a particular piece of functionality in Erlang due to the way the organization of the standard library accreted over many many years. I've really enjoyed adding Elixir to my stable of tools, and there are a couple projects at work will definitely be made significantly richer by the fact that they're built in Elixir.
- chippy 11y agoIn today's Who's Hiring thread, there is only one mention of "elixir". I quite like that as Elixir still has the aura of something new for its own sake with the type of people that this attracts.
- adambrod 11y agoMy company will be hiring soon and is using Elixir for backend services. Knowing Elixir is just a plus and any competent engineer can pick it up in a week. However, finding Elixir jobs is harder if you're the seeker... I agree.
- bratsche 11y agoThere are two really great additions to Elixir 1.2: multi-alias, and matching variables in map keys. Previously I found myself wanting to alias a lot of things, like: alias Foo.User alias Foo.Email alias Foo.Location Now with multi-aliasing I can do it all in one line: alias Foo.{User, Email, Location} That's just a cool syntactic sugar kind of thing that maybe saves a few lines at the top of the file. But the map key matching is great, and something that I've frequently missed up until now.