7 ms·
Anyone here switched from a statically typed functional programming language (Haskel, OCaml, F#, Scala...) to Elixir? How would you describe the experience? Wha
by insulanian 10y ago
Anyone here switched from a statically typed functional programming language (Haskel, OCaml, F#, Scala...) to Elixir? How would you describe the experience? What do you miss? What do you like/love? Overall, would you recommend taking that step?
- alexgaribay 10y agoI used to do Scala prior to coming to Elixir, mainly by using Play Framework to create web apps. I can tell you that I love Elixir and that I will not be going back to Scala. I miss nothing from Scala. * Pattern matching in Elixir is superior to Scala's in every way possible (You can pattern match on function parameters!!) * Async code is a breeze with Task.async()/Task.await() instead of mapping on Future's everywhere and making sure you have the proper implicit globals imported * Actor pattern is built into the language and it's a breeze to work with. No need to rely on Akka to replicate it * JSON is a joy to work with * Documentation is fantastic in the core language and many libraries * No more JVM! * Building a release is much easier than dealing with SBT If you have a functional background, I would recommend reading Elixir in Action as a starting point. It already assumes you have an FP background and takes you into more of the core features of the language. I really enjoyed it and the content is superb.
- hellofunk 10y ago> * No more JVM! You're just trading one VM for another, though. How does having a Beam VM environment differ from a JVM environment?
- alexgaribay 10y agoTrue. That bullet was more of my opinion of disliking the memory usage the JVM uses as well as my personal preference of VM. BEAM has many great advantages such as fault tolerance and multi-node distribution built in. This allows concurrency to be a first-class citizen for applications running on the BEAM. I'm not saying that concurrency can't be done on the JVM, but that I've found it to be much simpler using BEAM. On the other hand, the JVM excels at computational work compared to the BEAM. Both VMs have their place and can be better at different types of problems comparatively.
- andy_ppp 10y agoYou can also compile Elixir and Erlang to native code if you want it to run computational stuff faster...
- ngrilly 10y ago> You can also compile Elixir and Erlang to native code How? Can you provide a link about this?
- andy_ppp 10y agoAdd this at the top of your module (in Elixir): @compile [:native, {:hipe, [:verbose, :o3]}] :-o
- ngrilly 10y agoHi forgot about HiPE :-) But it doesn't produce a native binary, does it?
- andy_ppp 10y agoWhere did I claim it did?
- ngrilly 10y agoNowhere :-) I read too fast and mistakenly assumed native code = native executable binary. Is using HiPE a standard practice in the Erlang/Elixir community? What is the quantitative performance gain?
- lucidstack 10y agoThis comment from Reddit sums it up pretty well: https://www.reddit.com/r/elixir/comments/3gd1n3/what_are_the_downsides_to_compiling_elixir_code/ctx45xh https://www.reddit.com/r/elixir/comments/3gd1n3/what_are_the... I just discovered about HiPE as well, and I just gave it a try with a simple fibonacci module. Running fibonacci(40) went from 3.9s BEAM to 0.7s HiPE. I know it's a silly test, but it's pretty sweet to witness such a massive difference out of the box. :)
- tragic 10y agoTo me, there's an interesting point here. Elixir has the advantage of targeting a VM built for a language semantically similar to Elixir; things that have frustrating limitations in JVM functional languages like Scala and Clojure (eg, tail calls) just work on BEAM. Interop, naturally, is also much smoother. Want to call out to some Erlang code? Fine - that'll be ':module_name' instead of 'ModuleName'. On the other hand, the Java/JVM ecosystem is much larger, so there's a serious trade-off there.
- perishabledave 10y agoHaving BEAM specifically designed for Erlang concurrency gives it a number of specific benefits. Specifically in how it schedules and handles the VM processes to do efficient concurrency. For example, since the processes are in the VM, it can count the number of function calls to preempt a process that is taking too long. You can learn more about BEAM here: https://www.youtube.com/watch?v=_Pwlvy3zz9M&feature=youtu.be https://www.youtube.com/watch?v=_Pwlvy3zz9M&feature=youtu.be http://www.erlang-factory.com/upload/presentations/708/HitchhikersTouroftheBEAM.pdf http://www.erlang-factory.com/upload/presentations/708/Hitch...
- asonge 10y agoThere are a bunch of different performance differences, but a couple basic differences: 1) gc is per-process, not global/stop-the-world 2) the VM is responsible for scheduling processes using threads, and can pre-empt...blocking the scheduler is considered a VM bug.
- phamilton 10y agoI find failure to be more fatal on the JVM. That's neither a bug nor a feature, it's just what it is. For example, BEAM puts the process call stack on the heap, so you don't need to tune them separately. You won't hit a stack overflow, you'll just run out of memory. Many, many characteristics like that exist. I prefer a working slow system over a broken system, but I fully understand the preference for loud failures.
- rdtsc 10y agoI'll take BEAM over JVM any day.
- hellofunk 10y agoWithout any reasons for your statement, it's just an empty contribution. Care to explain why?
- rdtsc 10y agoAgree, sorry. Sure, here are some randomly ordered reasons: * Immutable data. This ties into "functional" section below but it is worth mentioning separately. The benefit here is it is a better fit for concurrency and correctness. * Lightweight processes. Can have millions of them. But they don't share the heap so act like OS processes in that respect. That means 2 things: 1) It changes the way you think and solve concurrent problems. It reduces impedance between real life problems and how they are solved. Spawning a new process for each long lived connection is obvious and easy. 2) Fault tolerance. Having one request not crash the whole server is a really a massive improvement. In C++ or Java you don't know if something got messed up because of a crash. Maybe some shared data structure or lock got left in an inconsistent state. There is just no guarantee. * Hot code loading. This is not just a gimmick but it works. Most places don't use it to update regularly and I don't either. But used it a few times in production to add extra logging, fix a customer specific issue without shutting down the cluster before the fix was released. All the while there were 100k/sec requests pounding it. That is plain old money in the pocket. No downtime, no headaches. * Tracing. BEAM has very good tracing support. When debugging I am quite fond of just logging into a node and using tracing instead of print or log statements. * Functional. This is more about Erlang the language, and it kind of goes with immutable data. But because of that it means state is more visible and explicit. Looking at a piece of code on a page, I get more context of what is happening because State is passed, updated and returned. As opposed to being some "this" reference which at that point in the code, I don't have any idea how it was modified or what it has in it. * Garbage collection. BEAM has excellent garbage collection. It is pause-less, in the sense that GC of one process won't block the world. Java has lots of tweaks for that but it is not a default state of affairs. Welp, this is just a quick list off the top of my head. At the end of the day, one can probably go through the above list and say I can do all that in Assembly or C. Which is true. BEAM is written in C in large part. To get fault tolerance, can just spawn OS processes in any language. To get immutability, can just go to Github and find an immutable collections library for Python or Java. Java can also do some code loading. But the difference is, it all comes in a single package ready to use. That is huge and I see it as a great benefit.
- acjohnson55 10y agoI haven't tried Elixir yet, so I can't really compare on your points, but a couple notes: You can use https://github.com/scala/async https://github.com/scala/async for async/await in Scala. It's super easy. Also, you can pattern match function parameters in Scal using PartialFunction `case` syntax.
- methehack 10y agoThere are optional type specs: http://elixir-lang.org/getting-started/typespecs-and-behaviours.html http://elixir-lang.org/getting-started/typespecs-and-behavio... which can serve as documentation and are used by a tool called Dialyzer during the build process to find errors based on the type specs. I have not used this particular tooling first hand, but my sense is that it is well-integrated and works well. Someone else will probably comment with first-hand experience. The Elixir compiler seems to catch a lot of errors, for what it's worth. If you attempt to call a function that doesn't exist or with the wrong arity, you're going to get an error (even w/o any type specs). The number of compiler errors one has in a statically typed language that are really just about types may not be that many. w/r/t static vs dynamic, in general, these are the things I'd consider (if you haven't already): you're domain (are you building a rocket or a consumer-facing web app), you're appetite for testing, size of project, size of team, specifics of the tooling w/r/t refactoring (elixir's compiler is pretty good for supporting a big rename, for example; ruby, without a compiler and with so many language features, not so much), how the language makes you feel when you use it (dynamic wins here in general for me; I don't like to be in trouble or interrupted when I'm thinking), the collections library (this is big for me -- I could never go back to a weak collections library -- Go, I'm looking at you), Etc. YMMV, qualifier, qualifier. In general, the specifics really matter -- both of what you're doing and the specific tooling and how they interact. Elixir seems to strike a very nice balance of all these things with a just right, small, extremely powerful feature set on a rock solid VM with astounding concurrency and distributed computing facilities, if you need them. By all means, I would try it.
- osense 10y agoDialyzer uses something called Success typing. The gist is that while e.g. Haskell won't compile unless it can prove that your code is correct, Dialyzer will only complain if it can prove that your code is wrong. Personally, when I used Dialyzer in Erlang, I was underwhelmed by the amount of errors Dialyzer caught (type checking concurrent code is hard, who knew?) — however, it is certainly better than nothing. Plus, the type specifications you have to annotate your functions with help with documentation :)
- shrugger 10y agoI switched from Ruby to Scala, and I have had an absolute blast. Elixir is sort of chained to BEAM, which doesn't appear to have as bright a future as the JVM or LLVM does, so Scala seemed like a safer bet. Reading about Elixir is cool sometimes, but then I look at Dotty, and I feel confident that I made the correct choice. I've also been keeping an eye on Crystal (statically typed Ruby-esque language, LLVM), but they aren't making great PLT choices so far. Maybe they'll get it together later. Scala-Native will blow it out of the water most likely anyways. Sort of the opposite of losing statically typed programming, but I've really enjoyed the journey and it's improved my work a lot more than I thought it would. I know Ruby pretty well and I used to feel really dumb all the time when things would break, and it took some time for me to realize that it was a language problem. Looking back and reading some of the Ruby that I ported, it was impossible to reason about, and very difficult to make guarantees for. Nothing was solid at all, and runtime errors could hypotehtically stop the show at any time. With Scala there's a much sharper baseline of what will definitely work or not work. Types make a LOT of things so much easier, in exchange for making a few things SLIGHTLY more tedious. After doing it, I'd make that trade ten more times if I had to.
- mykewould 10y agoWhen you say BEAMs future is not as bright, what indicators are pointing you in that direction?