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).
Elixir is truly an under-appreciated language. I've only toyed with it, and I'm really impressed with the whole ecosystem. Elixir, Phoenix, Ecto, Hex, etc all make a great ecosystem, and the awesomeness that is BEAM/OTP is just amazing. I loved the hot code deploys, and updating a system while it's running is something I've never seen before in action. Also Rustler is a great way to write CPU intensive NIF code too.
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?"
Same experience here. I have a process that I generally go through to compare languages...I rebuild my blog. It's an exercise that I've done many times and it gives me a time-boxed experience that compares work flow, database interaction, web requests, dealing with CSS/JS/assets, potentially caching, routes, email, search, etc.
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.
I believe the popular quote with Erlang is that Erlang makes hard things easy & easy things hard. Elixir was built around the idea of keeping the easy things easy. It does so by improving syntax, tooling, documentation & community in my opinion.
I believe I first read this idea in the book, Elixir in Action.
+1 for rustler. Writing NIFs (native implemented functions) in Rust can speed up your Elixir apps significantly. I think Rust & Elixir are a great duo.
I am super-stoked about the potential of Rust and Elixir, but there are some definite gotchas to be aware of. Especially if your Rust code is pretty expensive. Sonny Scroggin's talk about Rustler is really informative. https://www.youtube.com/watch?v=lSLTwWqTbKQ
Yes, I have. I would say it's pretty easy. Had it not been for rustler I wouldn't have touched NIFs since I'm not a C programmer. Also, rustler supplies elegant building blocks, which makes it a straightforward experience.
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:
I wonder how the popularity trend of Elixir has been lately. I know you can try to see it through GitHub or Google Trends, but as many members of the Elixir community use Slack I don't know if it's the best way to do it. One thing I'd like to see would be the evolution of downloads of the language and on Hex.
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.
> 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.
Rails downloads almost doubled from 2015 to 2016 (15M -> 24M). Not sure where you see that the "growth rate isn't increasing at all".
I've always thought that this is a consequence of tools like Docker, where each new image installs the gems from the beginning; but I could not prove my theory.
Indeed.com trends[1] show Elixir interest (though not yet jobs) surpassing both Haskell and Clojure right about now, which I found surprising especially given how much newer it is
It's got HN hype and a lot of the negatives that come with that (awful learning materials by people who haven't used it in production) and a decent amount of real world use though nothing major for now.
This seems to be the dominant use case for Elixir; migrate legacy Rails code to Elixir. When deciding between Go and Elixir for our startup I looked at both ecosystems. Go was significantly ahead in all categories: traction, articles on the web, packages on git, git activity, editor support ... I don't regret choosing Go but I always keep an eye out on Elixir. Pattern matching, pipe operator, immutability, supervisors ... I can only dream about that in Go.
I LOVE the pattern-matching/deconstruction/guards stuff. It eliminates SO much boilerplate logic. Just the function head of an Elixir function eliminates a dozen input validation and assignment lines in most other languages. It wouldn't be nearly as spectacular if it didn't pervade the entire language, though (for example, I'm sure you could get partway there in many other languages using a DSL)
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.
>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.
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.
> I LOVE the pattern-matching/deconstruction/guards stuff. It eliminates SO much boilerplate logic.
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.
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.)
Go doesn't quite have the right level of abstraction for building CRUD apps. In particular, working with relational databases is very manual. Even using things like sqlx.
For an improvement of 2 orders of magnitude while maintaining the same level of developer complexity, I'm hard pressed to think of any other web framework besides Phoenix that can deliver this.
Java and C# easily outclass Phoenix i performances, if only because they are statically typed, but also because they run on VM's that are more advanced (and admittedly older, so more optimized) than BEAM.
Java and C# outclass performance in raw CPU work certainly. Phoenix does not do raw CPU work however, it is primarily a web dispatcher on top of cowboy and the BEAM will run circles around both Java and C# systems if they are programmed to anywhere near the same quality of failure handling that the BEAM implicitly supplies (/me has worked with both Java and the BEAM for over 10 years).
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.
Java and C# incur more much more developer complexity for web development than Phoenix.
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.
Isn't that just a timing issue? Why chalk it up to HN immediately when it's more likely to be the general interest in the language increasing and more people using it for less time are writing about it? This is a good thing as these people will probably lead the future for its use.
It's just the name I give to languages or tools that get big online and generate a lot blog posts and shoddy learning material. Though most of the time it does start with HN.
BTW I love Elixir and I'm happy to see it grow. Nothing bad about HN hype it just has its positives and negatives.
I think is not that popular yet. Look at this issue for the sublime elixir plugin [1], it's breaks a lot of things and seems stalled for a long time...
Updating a system while running is something that has been around in the Lisp world for a while through the REPL. More recently it's a big part of the Clojure world -- I will usually NREPL into a running production system and "poke" around when there is a critical BUG that is only happening on production.
I'll take a crack at this. Elixir lays a really nice syntax, set of tools, and community over top of Erlang/OTP which are already amazing. While the language is new and increasingly popular, it is arguably not widely/well appreciated how nice and solid the language/ecosystem is at this point in its lifecycle.
I highly recommend playing with Elixir or another purely functional language. I've only gone through the Programming Elixir book[1], but it has fundamentally challenged how I think about solving problems in other languages.
Not for me. I've gone back and forth between projects that required functional languages, and projects that didn't across different companies. Bad code is bad code no matter what language it's written in. What makes me love my day job is whether I have the ability to make it better, and if those that work with me are aligned in wanting to do so.
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.
Low level code. Drivers, interfacing on COM/serial/USB ports, graphics programming or anything that requires more finely tuned data structures you have to manage yourself, low latency work where you can't afford to have a random GC happen at a bad point in the run loop...
But then you'd be ready to start on a new day job with tools and concepts you really enjoy using ;-)
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.
I got lucky and found an Erlang one. In general there are a lot less of those than other jobs. It's kind of a double-edged sword, there are lot of Java / JS / Python / C++ jobs but there are also a lot of programmers who apply for those.
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.
If you are interested in learning a purely functional language, I'd recommend against picking a dynamically typed language like Elixir.
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.
Well first, Elixir isn't purely functional. It's got side effects all over the place, it just doesn't have mutable variables.
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.
> there's definitely value in immutable data in a dynamic language.
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've been working with the BEAM (via Erlang) for over a decade, and with Elixir for almost 1.5 years, and I'd still give up, well, probably my current job if I could get a fully Hindley-Milner Typed Elixir...
Yes, mis-typed when I typed purely functional. My intent was to lean closer towards mostly-functional languages than languages which _can_ be written in a functional style (a la JS or Ruby).
I should know better than to use the word "pure" on the internet, someone will always correct how inaccurate my usage is :)
Functional languages are perfectly capable languages so you can typically use them for anything you'd use any other language for. But if you want a project that specifically showcases functional programming, writing a parser using parser combinators can be fun and instructive.
I don't like to think of a lot of these languages in terms of "functional". Haskell specifically does follow a functional paradigm, but Erlang/Elixir is more about the actor model and the functional aspects support that.
This book is for 1.3, and Elixir 1.5 just came out. Just a heads up, the author is currently working on "Programming Elixir 1.4". Believe it's coming out in November.
It's a fast-paced development! That's pretty great. I hope core team would consider slowing down a bit and catch up with Deployment, Monitoring(which Phoenix team working on it) and Platform(e.g. http/2) departments.
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)
Yep, I just finished to setup a build and deploy system for Phoenix using edeliver and it's definitely not nice. A bunch of files in different languages, it feels unnecessarily hard. I hope that'll put some effort in that.
I host the production site I'm working on at Gigalixir[1] (with the postgres DB in Google Cloud) and it's been pretty sweet. Deploys have been trivial (the way they should be, if you aren't interested in also becoming a devops expert). Jesse Shieh is extremely responsive and a committed founder. Unlike Heroku, Gigalixir does not restart its servers nightly, which is very relevant if you store any state app-side (such as a cache).
I wasn't aware of Gigalixir, thanks for mentioning that. Looks very promising.
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.
Elixir and Erlang deployments were tricky a few years ago, but I feel like now with distillery [0] it a lot better.
I use it in docker multistage builds [1] and have been really happy with that.
You may want to check out the recent 2.0.0 release candidates for the Cowboy HTTP server -- HTTP/2 support is one of the changes. (It's technically Erlang, but most Elixir projects I've seen use it for HTTP, generally through the Phoenix framework.)
Can anyone doing Phoenix in production share their typical HTTP response times?
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:
Phoenix creator here. The techmeme results are not representative of the framework. Several months ago they added Phoenix in a preview, but it was a very poor implementation. They were testing JSON benchmarks through the :browser pipeline, complete with crsf token generation. They had a dev DB pool size of 10, where other frameworks were given of pool size of 100. And they also had heavy IO logging, where other frameworks did no logging. We sent a PR to address these issues, and I was hoping to see true results in the subsequent runs, but no preview was provided this time and we weren't able to work with them on the error rate issues they ran into. After these experiences we've decided the core-team's time is better spent on the framework than chasing techmeme issues. If you go by real-world success stories from companies switching from Django, Rails, etc, you can certainly expect much better.
> The techmeme results are not representative of the framework.
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.
Okay, thanks for the reply. I asked about this benchmark once before (almost a year ago I expect), and was told roughly the same, so I was hoping things had improved by now. I understand it's just a benchmark and you have other things to do, but it does matter to me and I expect others. None of us want to invest a lot of time becoming experts in a new world and then not gain what we hoped. Personally these benchmarks make me think if I'm going to trade dev time for performance I should just use Rocket. That's probably not a reasonable position though. :-) Anyway, thank you for Phoenix, and I will look for opportunities to give it another spin.
I recently rewrote an (admittedly old and stale) django app from the ground up with Elixir/Phoenix. The website gets quite a bit of traffic.
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
You and blatyo are convincing me. :-) I really appreciate your openness in sharing these stats. I don't need to serve 2 million concurrent websockets. But I need to render HTML/JSON based on some database queries, under moderate traffic, and I'd like to get it under 200ms without trying so hard.
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!
The performance aspect also makes a huge difference in development. The application boots fast and the live reloading experience is rewarding. Having a 100 test cases that hit your endpoint+database running in less than a second is pure joy.
I can't stress how important that is. We have about 1.5k tests in our Phoenix app and they almost all hit the database - they run in 30 seconds. I compare this to a Rails app where 1k tests run 8 minutes. Having a fast test suite makes development so much easier and makes you rely more on tests.
One note on database time. If you're loading multiple related records, Ecto is able to do some of those requests concurrently. For example, if you get a user and their posts and comments, the fetch of user happens, and then posts and comments can be fetched concurrently.
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.
For single a web api server Elixir is going to be far behind, performance wise, against nodejs, the JVM and Go. Their big feature is reliability/clustering but in the context of web requests, scaling them is real easy today, just use a load balancer. For me Erlang/Elixir have very specific niche use cases(at which it excels at) but its fans confuse beginners promoting it as a "general purpose language" that they should use it for everything.
> For single a web api server Elixir is going to be far behind, performance wise, against nodejs, the JVM and Go.
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.
I believe what Overmind meant was that a single request in another language can probably beat Elixir in performance, but Elixirs ability to handle a large amount of requests concurrently means that it'll have better throughput.
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 think this is the best news all week! Congrats to the Elixir team. I love working with Elixir. Hopefully I will be able to contribute to the ecosystem soon. Excited about the future.
There's quite a few nifty little things in this one.
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!
Congrats on the new release! While this is all great news, it's still quite hard to get a full-time Elixir job outside of US. Kind of like staring at the candy shop display while it's closed. I'm wondering how to make this happen. I'm in a place where Elixir is just not going to happen and seems unreasonable to expect that I'll be able to convince people to switch to it right after joining a new place. Seems like the only option is to find spare time for playing with Elixir, but that proved to be difficult when I need to invested time in a different stack that actually helps me pay the bills.
Congrats to the Elixir core dev team for another fine release. The improvements to iEX's debugging capabilities are going to make a big difference to day-to-day developer UX. Thanks!
What an amazing release! I've never been as excited about a language and its ongoings as I am with Elixir. Thank you Elixir team for creating such a great language and making all of your work so accessable, transparent, and friendly.
For me it was that the mindsets of Elm and Elixir were very similar. Create small functions that accept data, and emit data, sometimes create a message with some data attached to it. Using pattern matching is very similar between both languages for matching on message types and shape. Also both languages share a nearly identical pipe operator, which influences the building of very strait forward function pipelines for transforming input or data into responses and output.
This line is about showing a snippet of the test when a test fails. We did this before but only for assertions.
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.
AFAIK it is a notation present in both the Lisp family and the ML family. In Lisp it means an empty list, and some dialects conflate it with nil. In ML it is a 0-tuple, but I don't know enough ML to say its relationship with nil but it seems tempting to conflate them as well.
it's one of the controversial points in lisp dialects. treating empty list as nil means it's falsey when used as predicate which has it's pros and cons.
for instance if empty list is truthy, this pseudocode won't terminate if tail is defined to always be a (possibly empty) list:
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
To make the intent clear in Lisp one would use UNTIL (NULL list) or WHILE (NOT (NULL list)) .
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.
Yes, I could. Though I would avoid using proper; the aim isn't to deem something "good" or "bad", just whether a name applies to it. An "improper" Lisp is very good and proper something else, and perhaps very Lisp-like language with a lot of conceptual compatibility with Lisp.
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.
strikes me as a detailed description of a very particular implementation that you specifically like. considering lisp is a family of languages - which of these rules do you accept deviations from and by how much?
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.
Heroku is OK as a deployment platform. Hex powers Erlang/Elixir communities on a small Heroku dyno ($7). And 99% of Elixir developers should not worry about hot code swapping anyway. Let your load balancer or your PaaS take care of it.
I use docker and docker-compose for sideprojects that don't need zero downtime deploys. Installed on a tiny digital ocean droplet.
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)
See above. Someone mentioned Gigalixir, and I've been having success with Clever Cloud. I had to do a ton of research before finding a workable option (Heroku is not really a good option imo), so hopefully this helps.
Using Heroku at the moment (largely because I was already familiar with its ecosystem) for a phoenix app, though they don't have support for Elixir. In the future I'm considering doing my own hot deploys to AWS, but the cost of running on Heroku is small enough that it may not be worth the time to migrate off.
Backend services that need high reliability, low latency, lots of concurrency. Lower p99 latency and better concurrency model than Java, more reliable/productive than C++.
I'm at Tinfoil Security, and we use Elixir for dynamic security scanning of web applications and APIs. We also have some Phoenix apps, but the bulk of our Elixir use isn't in web development.
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.
I use it for everything from bots to interacting with and controlling Java and Python programs and a lot more. The concurrency abilities of the BEAM have a lot of applications.
Before this change, if you wrote a module (let's call it MyFoo) that implemented a behaviour, your only clue would be the `@behaviour Foo` near the top. All the functions in MyFoo would look the same; you'd need to look in the Foo module to look at Foo's list of callbacks if you wanted to know which of MyFoo's functions implemented Foo's callbacks.
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.
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).