Elixir 1.5 released
github.com
github.com
We have published a draft version of the announcement since the release notes are not super helpful for those unfamiliar with Elixir. Is it possible to update the link to the official announcement? Thank you!
EDIT: We are done with the changes on the draft. We've added asciicinema snippets to show some features, improved the section on Calendar changes and also mentioned the compilation time improvements (expect at least 10% faster compilation).
I built a side-project powered by Elixir & Phoenix 1.2, I found it so surprisingly quick and easy to accomplish even complex functionality. Every time I implemented a new feature server-side it honestly felt like "Is that it? Really?"
I believe I first read this idea in the book, Elixir in Action.
It's not a perfect measure but it does a solid job of giving me the whole experience of working with a language on something similar to day to day and separates the "this is viable as a tool" from "OMG! BENCHMARK!" type experiences.
Doing this with Elixir and Phoenix was mind blowing. It was so clean, efficient to work with, efficient in performance and the design decisions around the language almost ensure you'll avoid entire classes of debugging / maintenance issues in the future. I was blown away.
Wrote about it here: http://www.brightball.com/articles/insanity-with-elixir-phoe...
Keep in mind, there are a number of things that I did there that could have been done better/cleaner. It was my first experience with the language.
I've had a few issues with the version of rustler published on hex.pm not working with Erlang/OTP 20, and I've tried using the master repo as a dependency in my `mix.exs`, but that didn't work since rustler repo has an unusual directory structure which fails to compile. And then lo and behold, I've discovered how amazing the `mix` tool is and via `mix help deps` I've learned that you can actually check out a specific directory (via `sparse` option) from a remote repo as your dependency.
Now my dependency listed in `mix.exs` looks like this:
{:rustler, ">= 0.0.0", git: "https://github.com/hansihe/rustler.git",
tag: "0.15.1", sparse: "rustler_mix"}
... and problem solved. I guess peeking at rustler's tests helped me a lot.All in all, the entire Elixir ecosystem is really elegant. Such a joy to write code now!
https://blog.discordapp.com/scaling-elixir-f9b8e1e7c29b
https://blog.discordapp.com/how-discord-handles-push-request...
http://www.techworld.com/apps-wearables/how-elixir-helped-bl...
They went from 150 Rails servers to 5 BEAM servers "and could probably get away with two" (!)
Same thing with immutability. If it doesn't pervade the entire language, it feels slapped-on, and you basically lose most (all?) of the guarantees (like removing an entire class of bugs caused by mutability).
I saw what you saw in Go, but in doing my homework, I also saw an astonishing amount of ugliness[1][2][3], and additionally I took a bit of actual offense to the core philosophy of Go's design as stated by Rob Pike himself[4][5] so I am betting on (hoping for?) spectacular Elixir adoption I guess lol, as my current and all future projects for the foreseeable future will be in Elixir.
About the only wart I've seen so far in Elixir is the pin operator[6], but that was necessary to preserve the name-rebinding ability in a pattern-matching context, and it stops seeming like a wart fairly quickly, once you realize why it's necessary.
[1] https://anvaka.github.io/common-words/#?lang=go makes it seem like 50% of the day-to-day code in the language is error-checking due to the lack of exceptions
[2] https://github.com/ksimka/go-is-not-good
[3] http://byrd.im/go-is-poor/
[4] http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-in...
[5] I'm actually a fan of Plan9 and appreciate Rob Pike's work on that
[6] https://stackoverflow.com/questions/27971357/what-is-the-pin...
I recently ported some simple plaintext operational transform code to Go and Swift to compare the languages, and this is so true. A lack of parameterised enums and a decent match block resulted in the Go code being about 50% larger than the swift equivalent. And the extra size bought me nothing! I find the Go code to be less readable and it had more bugs out of the gate.
IDE screenshots:
https://twitter.com/josephgentle/status/876639761166770176
Its a shame too, because I adore Go's concurrency features and APIs. Server side swift seems barbaric, and I lust over Go's scheduler and networking APIs.
Maybe its time to give Elixir a try. It sounds like it might be at a nice sweet spot of modern language features, concurrency and a mature ecosystem.
(NB: I'm new at both languages. A more experienced Go programmer might write that code differently. I don't find myself wondering that with Swift because its much more idiomatic.)
I'm interested in hearing more on this, because I find elixir's pattern matching phenomenal. Fully embracing it feels like such a paradigm shift, and along with the rest of elixir it feels like I'm learning programming all over again (and I've been doing this for over a decade). I love it.
Back to the pin operator - the syntax is very light, and it's conceptually simple. As you said it's a natural consequence of pattern-matching. I'm not trying to start bikeshedding here, just wondering if there are some other problems or perspectives with the pin operator I'm not aware of. Thanks.
Also, the Erlang VM is older than the JVM, initially created in the late 1980's. The JVM, according to wikipedia, was introduced in 1994. Also the BEAM has significantly better GC handling that both the JVM and .NET both since it has a segmented memory model (each actor has segmented memory) unlike the JVM and .NET's monolithic Heap's, this allows it to perform vast optimizations that ensure that the GC is almost never called yet memory is properly and fully reclaimed due to the bounds of the individual Actor heaps, and even when the GC is called it does not stop-the-world or anything of the sort and has multiple layers of GC's that run for specific cases, the system stays running even as the GC's (rarely) runs. The average GC run time even when it does run is measured in the single-digit 'micro'seconds. If anything the BEAM VM is not only just much older than the JVM and .NET VM's, but also more advanced.
And as the the sibling comment points out, raw CPU performance isn't the only measure of efficiency. The JVM loves to eat memory, and if you get 100x CPU efficiency but use 10x the RAM, you're still bounded on machine resource usage by that memory usage.
https://en.wikipedia.org/wiki/Erlang_(programming_language) https://en.wikipedia.org/wiki/Java_virtual_machine
BTW I love Elixir and I'm happy to see it grow. Nothing bad about HN hype it just has its positives and negatives.
[1] https://www.indeed.com/jobtrends/q-Erlang-q-Elixir-q-Haskell... (scroll down to 2nd chart)
http://www.reallyhyped.com/?keywords=elixir%2Cerlang%2Ccloju...
It tough now since the web space is very competitive.
Before that it's just PHP (well it displaced Perl) and then RoR pop out to give it a real competition. For a while you'd think Ruby was going to over take PHP for web dev but it eventually converge to a steady state the growth rate isn't increasing at all. If you look at tiobe index and red monk's for language popularity Ruby have either stayed teh same and move down a few spot. Javascript just sky rocketed after nodejs (this is relative I remember the first year or so where it was slow in term of growth, hype, and adoption).
There are so many web dev pie out there for each language to take a chunk. After RoR was nodejs, this is on top of the other smaller player groovy, python django, java stuff, etc.. a least major players within the startups that I've experiences.
I believe Elixir and Erlang is a very great language for web dev. Unfortunately it comes into a time where the market is very competitive with many alternative out there staking a claim for this field.
At this point the web industry is really really hype imo. And people eat this up like candy.
I can say for sure Elixir is a better concurrency model and better language than NodeJS will ever be for web development. And the hype if there is any is real for Elixir.
Rails downloads almost doubled from 2015 to 2016 (15M -> 24M). Not sure where you see that the "growth rate isn't increasing at all".
Source: RubyGems db data dump (more stats here: https://infinum.co/the-capsized-eight/analyzing-rubygems-sta...)
Massive thanks to the devs who work on it.
[1](https://pragprog.com/book/elixir13/programming-elixir-1-3)
It's not just a matter of syntax and such but a whole new way of thinking - specifically immutability, functional aspect, using lightweight processes, hot code loading, sane handling of crashes and restart, easy tracing, etc. allow approaching and solving problem in whole new ways that is often a lot more efficient (both performance wise but also operations-wise).
Even if you switch to using other language you'd find yourself trying to apply some of these techniques so it is a useful set of things to learn about.
But agreed, it's still worth the effort to learn as many new languages as possible. It will make you a better programmer.
Haskell and Erlang were particularly eye-opening for me, but Scheme/Clojure was a great entry point into FP.
If I had found an Elixir job I would have taken that as well, most of the harder to grok concepts are pretty much the same between the languages. And I do prefer Erlang I find it simpler so far.
I think practitioners of functional languages get a little preachy when really, exposure to functional languages should just be assumed to be part of the basic training of any engineer. It's a tool and as good as it is for some things, it's absolutely awful for others.
Lots of things.
Can someone suggest a fun project, which can showcase the features of functional programming?
Functional programming only starts to show its power with types and parametric polymorphism (higher kinds, etc...). Without type annotations, all you get is a watered down, crippled version of what a functional language can achieve.
Second... While I love static typing as much as the next guy, there's definitely value in immutable data in a dynamic language. You also get Dialyzer in Elixir/Erlang, which is an interesting alternative to the usual type systems you find in Haskell/Rust/etc. in that it focusses on finding places where there's provably a problem, rather than where it's not provably correct.
Sure, but there's even more value in immutable data in a statically typed language, because of all the advantages that come with such a language (automated refactoring, better performances, tooling, etc...).
I should know better than to use the word "pure" on the internet, someone will always correct how inaccurate my usage is :)
https://pragprog.com/book/elixir14/programming-elixir-1-4
Anyone have any other suggestions on up to date Elixir books?
v1.5 seems to have a bunch of bug fixes and deprecation (Hah! I'm not sure if it's like move fast and break thing). It is potentially the case.
In every important part, there seems to have a solo smart person working on it. E.g. Cowboy(I know it's erlang but Phoenix depends on it significantly), Distillery. That could be a good thing. Less people may catch up with each other faster. It also mean a load of works! And also mean some convention are out of sync (e.g. configuration which I think Conform is the proper way lately)
It is definitely not the case. :) If anything breaks, please fill in a bug report and it will be fixed immediately.
[0] https://github.com/bitwalker/distillery
[1] example dockerfile: https://gist.github.com/bsedat/16cb74ebc8ab0ed61ac598a129b0a...
I've been hosting my site at https://clever-cloud.com with good results. I've been using Docker there but they just added beta Phoenix support which makes it really easy. They're French, and I'm in the US. So there have been time zone issues and support has been a bit lackluster at times, but generally they've fixed all the issues I've brought up and have been responsive. Price is right.
I built a small Phoenix project about a year ago, and compared to Rails it wasn't quite as fluent but still pretty nice. But ever since then, I've been trying to decide if the extra development time is worth it for the performance gains. I get that Elixir is more scalable, and I love how the RAM requirements compared to Rails are tiny, but what I still haven't been able to really answer is the latency improvement. According to these benchmarks it is about as fast as Django:
https://www.techempower.com/benchmarks/#section=data-r14&hw=...
Is that really the best I can hope for?
The one at the top is proxying the request to a java app which happens to be a little slow.
http://www.phoenixframework.org/blog/the-road-to-2-million-w...
I've seen several instances of this, now. Some Rails benchmarks jumped up pretty high as well when they managed to get someone to competently configure Puma. Practically the same story, just changing out names.
Take techempower benchmarks with a boatload of salt. Not only are they not particularly representative of your real world use cases, they apparently are often not representative of competent use of the tools they're benchmarking.
Hopefully this is an issue the techempower people figure out some way to address. It would be nice if this was a more trustworthy resource.
I went from an elaborate multi-tier caching setup, with varnish and memcache, to a ZERO caching setup. The amount of complexity reduced by doing this is huge.
The Elixir app hits the postgres db for nearly every request and I'm getting average response times around 45ms. Quite a bit of that is database wait time. It's super stable and efficient. And I'm running it on a dirt cheap, tiny node in the cloud, where before I needed two small EC2 instances to keep up with peak loads.
Also, now that I've gotten the hang of it I think it's actually more efficient with regards to development than either Django or Rails.
Here are the google crawler response times directly before/after the switch to Phoenix: http://imgur.com/a/FASyJ
I mostly agree with DHH that response time is dominated by database queries and Rails is "fast enough". Most problems you can fix by improving your query patterns or doing some SQL tuning. And yet . . . Rails is still awfully slow! Most companies don't have time for Russian-doll caching, let alone making the designers consider that at design time. I would love to use something as effortless as Rails that still gave me snappy performance well into the app's maturity.
I'm fairly confident Elixir can do that, but it's hard to look at these benchmarks and come on HN and hear the Elixir folks saying, "Just trust me." There is a strong temptation to walk away thinking it just doesn't live up to the hype. So having some hard numbers is a great reassurance. Thank you!
Also, when I used rails, quite a bit of time was spent wrapping the data into active record objects, whereas Ecto returns simple data structures, which seems to be much faster.
To some Go web api frameworks perhaps.
To the JVM, not really. The frameworks I used with it in the past (spring/play/coupleOtherSmallOnes) are throttled to the number of threads for concurrent connections. The BEAM (Erlang/Elixir) has no such limitation and it blew away my old Java servers handily just due to its concurrency alone.
And not to nodejs at all. Running a single BEAM vs a single node there is no comparison, the BEAM runs circles around it. With nodejs you can shard it out to multiple running instances to get concurrency better but you run into OS limits far before the workload that the BEAM can handle.
For example, Jetty will beat every HTTP hello-world you can write in Go. I know because I've tried to beat Jetty in Go.
For example, if a web request in framework A takes 100ms and framework B takes 200ms, but framework B can handle 4,000 requests concurrently and framework A can handle 1,000 requests concurrently, then framework B will beat framework A in handling 20,000 requests.
framework A - (20,000r / 1,000r) * 100ms = 2,000ms
framework B - (20,000r / 4,000r) * 200ms = 1,000ms
I'm not sure I like the child_spec change, personally I like the supervision mode to be explicit when calling children.
I do like the developer tools, the breakpoint support, the UTF8 for atoms (which I'm realizing we may want in our DSL since we're converting user input strings to atoms), and the @impl that allows to explicitly declare which functions are there for an interface.
Overall, it's amazing to be part of the elixir community, rarely have I seen such emulation, positivity, speed of growth, and effectiveness achieved so fast for a language. Congrats @josevalim for bring the power of BEAM through a wonderful syntax!
careful there. Theres a hard limit on the number of atoms that can be created in an environment, and serializing user input to atoms can get dangerous
Seems like a pretty good language endorsement to me lol
EDIT: Here's a "curated list of companies using Elixir": https://github.com/doomspork/elixir-companies
mix test mix docs Genserver Pattern matching
The list goes on, you find yourself in The Zone more often.
http://www.phoenixframework.org/blog/the-road-to-2-million-w...
Well done!
[0] https://www.dailydrip.com/topics/elixirsips/drips/phoenix-an...
I personally haven't tried it out of personal preference and instead had a great experience coupling Vue with a Phoenix backend.
There is an ElixirScript project in current dev, still early but usable, that compiles Elixir code to javascript too.
I've been using Elixir for almost two years now and it's no silver bullet, but overall it has been a really great experience.
[ExUnit] Show code snippet from test source file in case of test errors
ExUnit backtraces have historically been a bit hard to read sometimes IMHO.
I am afraid this change will not improve the qualify of the stacktrace itself.
If you run into a situation where the test report is less than ideal, please open up an issue so we can discuss if there is something that can be done about it.
for instance if empty list is truthy, this pseudocode won't terminate if tail is defined to always be a (possibly empty) list:
while seq:
head, seq = seq.head_tail()
f(head)NULL is a predicate which does the same as NOT, but makes the intent clear. It also allows to move the code to a dialect where NIL and FALSE are different.
Parens aren't used for any collection type in Elixir ( `(1,2,3)` is just a syntax error), so the lispyness explanation for () being nil in Elixir, while neat, doesn't really make sense
Sussman and Steele had the good sense not to call Scheme "<something> Lisp", because they knew that it would "ring falsey".
In a Lisp:
* expressions evaluate their sub-expressions strictly, usually in a left-to-right order unless otherwise noted (in the case of control constructs which repeat or omit the evaluation of some parts, and such).
* evaluation of all expressions either always produces a value, or in he case of multiple value support, always produces a tuple of zero or more values. In any case, when an expression appears in a spot where its value is required, its first value is taken, and if it returns no values, its result is taken to be nil.
* Tokens consisting of nothing but the 26 upper and lower case letters denote interned symbols. Two symbols nil and t are special in that when the are used as expressions, they evaluate to themselves and may not be used as variable names. Symbol names may be case-insensitive/folding so that NIL and nil denote the same object.
* A type exists called a cons cell (or just "cons") representing a pair of values bound together. It is produced by a two-place function called cons which creates a cons and initializes its two fields from those two arguments. The left argument initializes a field called car, and the right argument initializes a field called cdr.
* A pair of unary functions car and cdr take a cons cell argument, and retrieve the car and cdr field, respectively. car and cdr may also be applied to nil, and return nil.
* Cons cells are mutable, except possibly cons cells derived from literals expressed in program source code (for the sake of being able to put compiled program images in read-only memory, and condense their representation by collapsing identical conses). The functions rplaca and rplacd mutate the car and cdr of a cons.
* The printed notation for a cons cell is (a . d) where a recursively denotes the printed notation for whatever object constitutes the car, and likewise d is the printed notation of the cell's cdr. In the special case when d is the object nil, the (a . nil) notation condenses to just (a) which is understood to be equivalent.
* Lists are represented by cdr-recursive chains of cons cells: a list is zero or more conses, referentially linked via cdr fields, with the car fields used for the containment of the list elements. The symbol nil appearing in the cdr of a cell indicates the end of the list. A cons cell appearing in the cdr of a cons cell indicates that the list continues. A value other than nil or a cons cell also terminates the list, but "improperly": the list as a whole is called an "improper list".
* The symbol nil by itself represents the empty list. There is no "improper empty list": a non-empty list begins with a cons cell. (In some situations, there is an "emergent phenomenon" in which a non-nil atom behaves as an empty improper list; e.g. (append '(1) 3) -> (1 . 3).
* The symbol nil also denotes the (one and only) Boolean false value. A form which returns a Boolean indication returns nil to indicate "false", and any other value to indicate "true". The symbol t is a canonicalized representation of truth.
* Every object which is not a cons cell is an "atom". The consp function returns t (true) when its argument is a cons cell, otherwise nil. Its logical opposite is the atom function which returns t for an atom, and nil for a cons cell.
* A Lisp supports the functions and operators: null, and, or, cond, eq, equal, apply, eval, quote, cons, car, cdr, rplaca, rplacd, list, append, lambda and let.
Hardly at all; even the 1960 Lisp 1 manual ran for some 160 pages; this is just a few bullet points. It leaves a lot of room for family inclusion.
But not every Tom, Dick or Harry that walks in off the street is your family member, or even a friend.
> very particular implementation
Nope; just the original thing and many of its derivatives that can legitimately be called some kind of Lisp.
"Lisp" is in fact the name for a particular set of implementation features.
You may have a very nice implementation of some sort of list processing with all the equivalent expressivity and power, or whatever measure of pedigree we choose; it's just not Lisp: pick another word.
> which of these rules do you accept deviations from and by how much?
None. These are the things someone shouldn't mess with, if they want people to refer to their programming language as a Lisp dialect.
And, in fact, at least if we look at major works in the mainstream, most of those who do change those things understand this and don't use that term in naming their language. So, a fairly good approximation to the predicate "is not Lisp" is "does not have 'Lisp' in its name".
Also false. The requirements could be implemented by something I strongly dislike. For instance, someone's crappy one-weekend Lisp dialect, hopelessly unsuitable for real work, in which an error stops the entire process without leaving a clue where it occurred. I will certainly prefer a quality Lisp-resembling language to such a thing.
There is also https://github.com/hashrocket/gatling that promises the Git push workflow but with hot upgrading capability.
A multistage build makes it easy to compile a release on a macOS system and create a minimal alpine docker images with the unpacked .tar.gz release. (My app is an ~84MB docker images)
It's a very IO-bound problem (how many requests I can make while staying within rate limits / not taking down a service), so Elixir is a great fit for coordinating all of the concurrent work involved in security scanning.
Other uses where Erlang shines are a great fit for Elixir too: WhatsApp, Goldman Sachs uses Erlang for Trading, Heroku's routing mesh, ...
I think with Nerves, Elixir fits well on embedded platforms. Its supervision trees make it easier to create fault tolerant systems, and the actor model is great for concurrency.
Now with this change, you are free to mark those functions in MyFoo with `@impl true`. It's entirely opt-in, but once you use it, it enforces the presence of `@impl true` on all MyFoo's callback implementations. This allows the programmer to make these functions' purpose clear, and uses the compiler to make sure the annotations aren't stale or incorrect.