Phoenix 1.0
phoenixframework.org
phoenixframework.org
I'm an indie developer building such a back-end (social networking/chat space), have full choice of language. Started using Go earlier this year and mostly happy with it.
Should I switch to Elixir in my next iteration? Would it make me more productive, or save me from various deployment hurdles in long-term?
(Please don't take this as one of those mostly aimless "Hey, is Ruby or Python better?" type of questions. I hate those myself. I'm going to be investing thousands of hours into Go at this point. Hoping for some serious pro-vs-con discussion, hoping people who have architected something big in either language could chime in -- such is the major plus of asking on HN.)
I tried Googling, and the best/most recent I found was this thread. [1]
[1] https://www.reddit.com/r/elixir/comments/3c8yfz/how_does_go_...
Community: smart people (who I respect) in the Ruby community are getting really excited about (and choosing) Elixir. People like José Valim, Dave Thomas, Bruce Tate, Chris McCord, etc.
BEAM and OTP: The Erlang VM and OTP have been battle-tested at Ericsson. It's known for having 9 9's of reliability and scaled WhatsApp to millions of simultaneous connections.
HEX: like Rubygems was for Ruby, Elixir/Erlang has a budding package management system via Hex. Hopefully this becomes the canonical source for libraries.
Phoenix: Rails popularized Ruby and became the framework of choice for quickly and pragmatically developing CRUD apps. Phoenix has Rails-like conventions in building an Elixir app and has built in support for websockets. This framework is built for today's technology.
Syntax: Coming from Ruby, the Elixir syntax is approachable and understandable. It's easy to jump into without having much prior knowledge.
Kinda subjective, but those are reasons why I'm excited and choosing Elixir to build future projects upon.
By contrast, if Elixir just works, it's useless. Its functionality comes almost entirely from Erlang. Therefore its whole reason to exist is to make using that power more pleasant.
That's why, for example, Jose Valim has said "if you see a bad error message in Elixir, which makes you confused and does not help you solve the problem, pls open a bug report." https://twitter.com/josevalim/status/621933537009246208
Elixir's functionality comes from BEAM and the language, not Erlang.
How "similar" internal representation needs to be to its textual version to be homoiconic is subjective.
In Erlang an expression:
2+3.
yields this AST: {op,1,'+',{integer,1,2},{integer,1,3}}
You can strip line and type annotations (you could also easily add them to the Prolog example below), which will get you: {'+', 2, 3}
If you scroll down the Wiki page you cite, you'll see an example in Prolog, where this: X is 2*5
yields AST of this shape: is(_, *(2, 5))
The important similarity here is that all elements of ASTs are still first class objects in the language. You can manipulate them in their raw form with the same functions you'd use for manipulating any other data. In other words, once you have an AST, you don't need to evaluate it, it's enough to just read it.This is not true for Python. An expression:
2+3
yields: Expression(body=BinOp(left=Num(n=2), op=Add(), right=Num(n=3)))
An AST here cannot be manipulated in its raw form here. To manipulate it - the representation itself - you'd have to parse it again or evaluate it to use special methods on AST objects.So this is the practical definition of homoiconicity I came up with. You are of course free to disagree. I'm stressing "practical" here, because what I'm interested in is how easy it is to manipulate the AST to write macros. Homoiconicity for the sake of homoiconicity is of no interest to me.
PS. BTW, maybe I should base my argument on Lisp instead of Prolog. If you read the Wikipedia page carefully you'll see the part on Lisp says the same thing I do above.
I don't find it particularly subjective, it's just what it means. According to what you're saying any language that can be parsed and manipulated by the language is homoiconic, since the AST can be represented by types available in the language, no?
Literal datatype.
And please, prove it to me that "Erlang isn't that". My examples above indicate quite clearly that yes, it is.
> I don't find it particularly subjective,
I was referring to the word "similar" which appeared in the definition of homoiconicity given by flackjap.
> since the AST can be represented by types available in the language, no?
Yes, if the datatypes used in AST representation have literal forms in the language. No otherwise.
> In computer programming, homoiconicity [...] is a property of some programming languages in which the program structure is similar to its syntax, and therefore the program's internal representation can be inferred by reading the text's layout. If a language is homoiconic, it means that the language text has the same structure as its abstract syntax tree (i.e. the AST and the syntax are isomorphic). This allows all code in the language to be accessed and transformed as data, using the same representation.
As I noted, a similarity is subjective, but I never claimed that it's not needed as a criterion. So, what I claim is that homoiconicity happens when the AST representation consists of only literal datatypes of the language AND the AST structure is "similar" to the original code.
That's it. And also:
> I can represent an AST in array literals in essentially any language
I doubt it, but that's irrelevant. Had you done it you'd essentially reimplement the language of your choice and then we're not talking about that language in general anymore, but about your implementation. What you say here is that "every language can be made homoiconic given appropriate AST implementation". And that's probably true, although I suspect it gets too hard to do in practice for more complex syntaxes.
May I ask where are you getting your strong convictions about homoiconicity from? If you read the Wiki page you'll notice the use of less than precise words, like "similar" or "Languages which are considered homoiconic include" and so on. The concept itself is not as clear-cut as you seem to believe and it's mostly defined by examples.
Also, you still didn't provide a convincing argument that Erlang is not homoiconic; you only claimed that "it isn't" and moved on.
EDIT: as an example of how subjective homoiconicity is take a look at Julia. Listed on the wikipedia as homoiconic, here are the details: http://docs.julialang.org/en/latest/manual/metaprogramming/ - if Julia is homoiconic, then Erlang and Elixir are too. And Haxe, and Dylan. Are they? I don't know, I'm not going to argue about this. As I said, homoiconicity is only interesting as a way of simplifying macro creation; any more discussion is honestly useless to me.
Here I am pimping my own stuff but I wrote a related article on this:
http://lebo.io/2015/06/22/the-unix-philosophy-and-elixir-as-...
"The Go devs have since stated that they were surprised to see that a lot of Go converts were from dynamic languages like Python and not C or C++. Go still makes sense for a lot of apps ... somewhere, however, that has been extrapolated to the idea that Go is a good language for writing web apps."
I think this is the crux of the question. And heck, it's very easy to spin up a web server in Go, and so many intro examples focus on that.
Go is really compelling in producing a single-binary application... but for web apps, I think Elixir wins because it's working at a much higher level, and thus you're more productive.
After a long stint as a python dev, I find myself seemingly almost subconsciously avoiding languages that require a ceremonial dance and some type of sacrifice to get all the various bits (dependencies, etc) in just the right place before the app will start up properly.
Forgive me if I've missed something. I'm just getting excited about elixir at this stage.
We use "mix release" to build the tarball, scp to the server and unpack, then run using an upstart unit which runs "exec su -s /bin/sh -c 'exec "$0" "$@"' myuser -- /path/to/deploy/directory/bin/myapp foreground"
It's pretty painless. We are automating with Fabric now, but will likely be switching to Ansible soon.
Optionally, you could cross compile locally or compile on a build server and have the other nodes pull from there, same as you would do in Go.
However, I'm not sure if bytecode compiled with an Erlang version >=17.0 will run on earlier versions of Erlang if it makes use of maps. (Maps are a new type that was introduced in Erlang 17.0.) I should really test this.
You can read more about pros and cons of statically and dynamically type languages [1]
[1] http://programmers.stackexchange.com/questions/122205/what-i...
For example, Elixir is a more "strict" dynamic language than your usual Python/Ruby/Javascript. Data is immutable. There is no monkey patching. Most state changes happen explicitly via process communication. The macro system is compile-time which means nothing will pull the carpet under your feet at runtime.
Also long-term productivity is about actually maintaining your system in production. And Elixir leverages 3 decades of experience on that, using a runtime designed to build systems that self-heal and are fault-tolerant (I slightly explore this here: http://blog.plataformatec.com.br/2015/06/elixir-in-times-of-...).
I don't want to give a yes or a no answer, I would just like to point out the line is much blurrier than that. It doesn't matter which type system you use, your code is going to have bugs or unexpected situations will arise, specially when we are talking about network. So knowing that your system system can heal itself is quite comforting.
Those are two complementary aspects. It is one of the reasons I would love to see a statically typed language succeed in the Erlang VM.
They're both statically typed, but the type systems obviously aren't equal. I would argue that stricter types are in fact one of the main things that helps me be more productive in languages with MLish type systems compared to C which lacks e.g. generics and proper sum types.
That said, I find Elixir very interesting for the exact reasons you said.
That was his point.
Elixir/Erlang aren't your typical dynamic language. Elixir is compiled and has pattern matching. I catch a ton of bugs at compile time in Elixir that I would never catch in Ruby/Python/JS until runtime. Examples of these are misspelled variables/bindings/function names and pattern match that will never actually match. Those are really, really common time wasters all taken care of at compile time.
Now what types of errors in Go really hurt you? Race conditions at runtime. I have to be way more careful about that to where it was costing me a lot of time in very concurrent programs. Eventually you develop a paranoia. Go has better tooling to help with this now, but concurrency and a language that prefers pointers just doesn't mix well. In Elixir I don't worry about this because everything is immutable. Now that GOMAXPROCS defaults to NumCPU I think a lot of programs that looked race condition-free probably aren't.
As far as runtime goes, Elixir and Go are at the same mercy but Elixir has much better debubbing capabilities than Go thanks to Erlang.
If you want something that gets you closer to static types and you have the discipline to keep up with running it and maintaining your type annotations, there's always dialyzer.[0].
It's an entirely different level of statically-verifiable correctness.
For example, if I have a function that returns {foo}, and I change it to return {foo, bar}, then a pattern match on its return value that does {Foo} -> ... will fail at runtime, and the compiler won't pick it up, right?
In a statically type language (such as Go), changing the number (or type) of return values will result in compilation errors until all callers have been updated.
Another example is instead of shuffling a bunch of bare UUID objects around (or strings, for that matter) in a system where lots of different things have a UUID, I can make a simple reference type for the IDs of different entities. This way, calling a function that takes the UUID of one type of entity with that of another can be a type error that's caught by the compiler instead of a logic error that's caught by a unit test. This is cumbersome at best to do in Java or C, and obviously impossible in Python or Ruby, but in ML-inspired languages it's simply the most natural way to work.
It might add some additional complexity in the first writing of the code, but in return you eliminate whole classes of problems forever. It's not just the initial writing that benefits (at some cost, admittedly), but all future changes won't have those problems either. In the case the types themselves need to change to account for expanded functionality or whatever, you again pay some cost in complexity, but in return every place the new type would cause problems you get a nice error.
The other thing to keep in mind is that whether or not these type are codified in the language they're there conceptually. Just because you have to write them down doesn't necessarily add complexity but is more like forced documentation that can be used to eliminate who classes of problems. It's difficult to see how this wouldn't intrinsically be better than so-called dynamic typing.
I'd dare say that diaylizer (Elixir's optional but easy to use type system) would lead to more maintainable code than Go's forced type system in the long run.
Orthogonal to all this is that I'm underwhelmed by Go's type system :/ If I was going to shoot for a language whose type system really helped me (in the ways I need/want help) it wouldn't be Go. It's pretty slick for some things (aesthetics aside) though.
I also agree that good type systems can reduce some forms of complexity (while often introducing another, but that's a different discussion).
> Would you say Go is more suited for high-performance command-line tools, and Elixir for long-term running stuff?
Like Go isn't very high performance. See for yourself: http://benchmarksgame.alioth.debian.org/ (I know, lies, damn lies and benchmarks, but it's the best we got!). Elixir is it good for marathons because it's based on Erlang and Ericsson claims six nines uptime? Just use the tech you find is most FUN to work with because it's better to have fun programming than being bored.
In the end you could use both, use the right tool for the job.
Using "lib/pq" (Postgres) for the db.
Also: need to cache some computed data in memory, and reload using a REPL or other means, haven't figured out the most "batteries included" way to do so yet.
Also: need to figure out the most production-friendly way to redeploy code (sounds like Erlang/Elixir can do really well in this regard.)
Elixir does nicely here, too. For caching, ets[0] tables are very easy to setup. For reload, you can use IEx to connect to a remote node and do whatever you need to do.
Good pick. The gorilla toolkit is definitely flexible. I typically use a mix of gorilla (context, csrf, schema) and Goji (routing, middleware chaining).
My 'hard and fast rule' is that everything needs to implement the http.Handler interface if I'm going to use it, so I don't get abandoned with a bunch of custom libraries that I need to refactor away from.
> Also: need to figure out the most production-friendly way to redeploy code (sounds like Erlang/Elixir can do really well in this regard.)
Most typically use the system's init daemon, and/or Supervisor/Circus/monit. I'm partial to Supervisor on that front for the cross-platform compat.
Also, any particular reason to not use a web framework such as gin-gonic for routing and templating? It simplifies some things down for me.
Re: web framework. Absolutely, no intention to reinvent the wheel. Just informative to rewrite various pieces in the initial stages to get a better grasp on the language/patterns.
That being said, I do miss active_support though; Elixir's utility libraries (fox, pipe, croma, etc.) doesn't yet have all the easy automagic that made rails so simple to develop on.
1) Referring to DHH and others as a "our old masters" instinctively bothered me.
2) While I appreciate that Elixir and Phoenix have Rails connections and can learn from it, I'd prefer it not become just a place for Rails refugees where it turns into a huge circle jerk about how Rails is terrible and Phoenix is great (which happens all too often in communities).
Other than that, I agree. But we should start something new.
As an example, Heroku uses cowboy (the erlang web server that Phoenix uses) for load-balancing incoming connections to all Heroku applications. The erlang VM (BEAM) is great for these types of highly concurrent, highly available, distributed tasks. The original use case for erlang was highly available phone switching for Ericsson.
To overcome the lack, I've used Resque (or beanstalkd in PHP, which has the exact same problem) as a background job manager, but then I had to write my own layer and rely on the database to handle the 'job' result.
Which parts of the framework leverage the concurrency model, other than the routing/request handling part?
I just start another process when you join a channel, and that process sets up the changefeed and pushes changes to the client in the form of HTML, allowing messages to be received and processed by the channel. You can watch the full presentation here: https://www.youtube.com/watch?v=aWaleoYD1Ro Slides: http://www.slideshare.net/bbhoss/otp-phoenix-channels-rethin...
Another example is sending email. In Rails, you need to have something like Sidekiq (or now Activejob) to be able to background the job so it doesn't block the response to the client. In Phoenix, you can simply spawn a process to do the work and move on. Sure, you might want a system like exq to keep track of things a bit better, but ultimately the concurrency primitives provides by Erlang/Elixir allow you to do everything you need.
I'll have a look at the slides
My understanding is that the cheap processes of Elixir would mean we could just keep a connection open to that user if we wanted to. Similarly, no need for a background processing framework like ActiveJob; just use processes.
And this works across the whole architecture. One of our projects right now is a mobile medical application for medical where caregivers communicate in real time with a number of patients. We have the mobile app talking to the server using a REST API and real time messaging for chat. The caregivers can communicate with the server using a web application with integrated web chat or via an XMPP client. And we have the normal public web and admin CRUD. All via a single server process in a single language. This is what Elixir/Phoenix was made for, it enables a new generation of modern apps.
If you're building another Twitter I would still use Rails. You'll be much more productive.
On the other hand, if you need to run parallel tasks or have mission-critical (aka can't go down for anything) work to be done I think you'll find Elixir the perfect combination of Ruby's syntax and Erlang's power.
Just my $.02 - I'm having a blast with Elixir at the moment.
On the other hand, if you are just building another web app, Rails is the better choice...
Sidekiq has been great as a background worker, but I'd like to try concurrency elsewhere.
Note that this was my first Elixir library and I was very much learning as I went along. Lot's of code that I want to refactor and extract.
Phoenix has really been exciting to use. It's a great way to get introduced into the OTP system from Erlang (plus all of Erlang's modules), it's incredibly fast, and the immutable data structures make it easy to reason about your concurrent code. I would strongly suggest giving it a try.
It's also worth noting that Ecto [1], the core-maintained Elixir ORM-like package, also hit v1 earlier this week and has backends for dealing with: PostgreSQL, MySQL, MSSQL, SQLite3 & MongoDB.
As someone who has used lots of ORMs I find the switch to a libary like Ecto very refreshing. It has an intuitive and very composable querying API and friendly DSLs for defining schemas and validations. These are the baseline features of any database/modeling library and Ecto satisfies them nicely.
But by far my favorite feature that has come in handy is that Ecto's concept of Repos does not couple you to a specific database. Unlike traditional ORMs that couple your objects to a specific database (read: the my_cool_app database in MySQL or Postgres) it's easy to support different databases within the same type of RDBMS or different RDBMS entirely. Since all querying in Ecto goes through Repo modules all you need to do is just create more Repo modules and configure them accordingly.
For some people this feature might not sound useful but if you've ever worked on an Enterprise or older app with multiple data sources or want to switch from MySQL to Postgres, this is a killer feature. Doing this with Rails' ActiveRecord is ugly, buggy, a pain and will bring you to your knees during Rails upgrades any time there are major changes in ActiveRecord.
Unfortunately, I don't have experience with using the ORMs you listed in anger so I can't make a direct comparison. Anecdotally, I have found it much nicer to use than Django's.
Very exciting that they are branching out to support MongoDB as well. I'd love if they could support more untraditional Postgres operators for arrays and json (I guess there's always a tension between least common denominator and using the specialized features of each DB). You can get around it with partials, but it makes the code more messy.
By the way, in case core team is reading, what's the motivation behind removing infer_model_view from the render functions?
Also Elixir will bring more people to the BEAM VM and take advantage of it, as I think it is a gem of engineering.
> NPM and RubyGems are casualties of people seeking
> open source fame and I hope we can avoid that in Elixir.
No, they're casualties of people actually using the platform, the platform's low publishing barrier, and the ecosystem's preference for focused libraries over monolithic bouncy castles.Rallying around one library sounds cool until you see that the top three competing solutions in another ecosystem each have more contributors and activity. Then you realize you're not in the elite ecosystem, just the smaller one that has one library like my tiny Texas hometown.
I'm not on the core team, but speaking as an Elixir user, explicitness trumps all virtues.
There are several key distinctions about Elixir vs the other languages you mentioned. These are things that are basically not going to happen in Ruby, Python, Go, Javascript, or etc.:
1) You get the benefits of Erlang/OTP as others have mentioned in their replies.
2) You also get the amazing macro capabilities (runtime code execution and runtime code generation, a la LISP) that Elixir brings to the table. Many of the language features of Elixir are written in macros in Elixir. The source to both Elixir and Phoenix are quite elegant and educational to browse, and demonstrate this runtime code generation aspect very well. It's straightforward in Elixir to introspect code, represent that code as data structures, manipulate those data structures, then generate or execute that code, as you can in LISP.
3) Immuatable data and functional style leads to better code in lots of ways. This is what really makes the benefits of OTP possible (updating the code without restarting the servers, easily migrating state between servers, and so on). But it also makes certain kinds of situations easier to understand and fix, since all state in the system can be expressed as parameters to functions.
Erlang provides great abstractions for building fault-tolerant, scalable, distributed, soft real-time systems. That's not to say you can't do it with Erlang, but Erlang does give some simple, yet very powerful tools for making developer's life easier.
Without Erlang you have to work harder to get similar effects. Again, it's not impossible but there's more burden on developers because the runtime provides less guarantees. I elaborated a bit on the topic in the promo interview for my book (http://www.infoq.com/articles/elixir-in-action-erlang-review).
I switched to Elixir and Phoenix last year and got the core of my app working.
It's funny though - the core is easier. But many freebies from Rails aren't there yet. So I still don't have password recovery emails or confirmation emails on signup done yet :)
Then you must create the login page.
Then the controller for authenticating. And then you need to ensure that the flow works with a test.
Then you need the email that actually activates the account, with the activation hash. So now you're setting up a mailer system, which Phoenix does not have by default.
Then people will want to recover passwords. So you need to write the logic for that. Oh, and the controllers and views. And routes.
And of course, you need to hash the password using some kind of encryption. Excrypt, comeonin, what have you. Choices choices choices.
You'll need a plug to act as the bouncer for your routes too, so nobody gets in where they shouldn't. So you'll have to write that.
You have to end-to-end test this, of course. And probably, if your business depends on it, get a couple other people to review the security of your system.
Simple. And takes a long time.
HTTP is pretty simple, but we use frameworks. SQL is pretty simple too, but we use Ecto now.
It's simple in its pieces, but I really don't wanna do all that work on every app. I'm lazy.
i'm not aware of anyone running an erlang or elixir repl over http but it would be an interesting project
https://pragprog.com/book/elixir/programming-elixir
From the website:
"You want to explore functional programming, but are put off by the academic feel (tell me about monads just one more time). You know you need concurrent applications, but also know these are almost impossible to get right. Meet Elixir, a functional, concurrent language built on the rock-solid Erlang VM. Elixir’s pragmatic syntax and built-in support for metaprogramming will make you productive and keep you interested for the long haul. This book is the introduction to Elixir for experienced programmers."
If you want a deeper look at Elixir - I'd recommend Elixir in Action by Saša Jurić (Manning publications).
Ben Tan Wei Hao's book is also promising (still in early release) - The Little Elixir & OTP Guidebook also Manning.
I'm pretty excited about Elixir and Phoenix. Building on Erlang's OTP should mean scaling can be fairly transparent.
http://www.phoenixframework.org/blog seems to point to the most recent post.
(edit: it is ":observer.start()" from inside iex (elixir repl) http://blog.plataformatec.com.br/2015/06/elixir-in-times-of-...)
Having said that, I've found it easy to get along with retuning JSON and the actual speed of responses is incredible. Completely anecdotal and unscientific but one service I recently converted from DRF to Phoenix saw drops in avg response time of 350ms to about 15ms.
However "Developer productivity" seems like an excessively vague term, and would be hard to compare in any meaningful way.
Getting my feet wet with a few side projects and am really loving Elixir and Phoenix. Performance is great and I don't miss too much compared to Rails. I still love Ruby and Rails, but will most likely default to Phoenix/Elixir for most future projects.
I like the screenshot of htop on the front page with all CPUs working along. And a shoutout to the Erlang's Observer tool as well, to inspect the running system and show process dependencies.
I'm looking into using Erlang for a new project that requires extensive scaling and concurrency and am coming from a functional background so may be more comfortable with the traditional Erlang syntax. However it seems that perhaps more development and activity is happening on the Elixir side of things and it may be more productive in terms of tooling, libraries (such as Phoenix and Ecto), and support.
Thanks!
They're both great languages, but I think Elixir is a bit more refined, learning from Erlang's advantages and disadvantages and improving on them. It's basically what you get if you watch "Erlang The Movie II: The Sequel" [0] and actually try to write a language for Ruby hipsters with excellent taste in noserings while humming along to Bananarama :)
Erlang developer tooling does need work. But we are getting there, we have a new build tool http://www.rebar3.org/ that also combines forces with Elixir for the package management https://github.com/hexpm/rebar3_hex
Another big thing is that the Elixir community focuses on ease of use and out of box experience the way the Rails community did. So it's easy to get started and all the pieces generally fit together well, e.g. the mix build tool works great, as does the hex package manager, and relx release builder. With Erlang it's more DIY. We have recently converted a big Erlang project to use mix as the build tool, and it just eliminated a bunch of cruft. The interop between Elixir and Erlang is easy. So you get the best of both worlds, the ease of use of Elixir with the power of Erlang, with the highly mature runtime and libraries. And with Phoenix we get a web framework with world class ease of use.
The syntax is nicer, but that's just a bonus. The real game-changer to me about Elixir vs Erlang is its macro system. This gives you runtime code execution and runtime code generation, similar to what makes LISP to powerful.
There's a large amount of boilerplate involved in creating an OTP server, as you know if you've done any Erlang. Elixir's macro capabilities completely eliminate all the boilerplate.
The source to both Elixir and Phoenix are quite elegant and educational to browse, and demonstrate this runtime code generation aspect very well. It's straightforward in Elixir to introspect code, represent that code as data structures, manipulate those data structures, then generate or execute that code, as you can in LISP.
Elixir also gives a number of excellent tools that streamline the support process over vanilla Erlang. For example, Elixir's runtime tooling automatically manages dependencies for you (similar to node's npm), and automatically maintains the application string that you need to provide for all OTP applications. It also has improved capabilities for testing, which are also made possible by the amazing macro generation capabilities.
> I'm looking into using Erlang for a new project that requires extensive scaling and concurrency and am coming from a functional background so may be more comfortable with the traditional Erlang syntax
Elixir's syntax is still just as functional. They support a regular if statement, unlike Erlang, but generally it's just as functional as Erlang. Elixir eliminates a number of needless chores from Erlang, such as having to end some lines of code with a comma, and others with a period, and then shuffling punctuation around whenever you add or remove lines of code. That's a task I used to do literally a hundred times a day in Erlang that I don't have to do at all any more.
I've looked at OTP the Elixir way and I do not see any real boilerplate reduction. The application-project dichotomy and the opinionated integration with a tool like Mix is also policy over mechanism.
rebar3 does fine dependency management given its constraints of having to unify packages coming from disparate sources.
The syntax is not nicer. It is a jarring conceptual mismatch to put Smalltalk-ish Ruby syntax over a language that eschews excessive monkey patching and dynamism like Erlang.
You can also do concurrency in Ruby. It is not the same as doing concurrency in Erlang though. The same way doing metaprogramming with syntax tools, parse transforms and what not is nowhere close to a macro system.
> I've looked at OTP the Elixir way and I do not see any real boilerplate reduction.
So please look again? Take a look at Elixir's agents or tasks and explain how it doesn't lead to more readable and cleaner code than the GenServer equivalent in Erlang for the cases they fit. You could maybe point other criticism but saying "no real boilerplate reduction" just shows you didn't really try or care to give it a try.
> It is a jarring conceptual mismatch to put Smalltalk-ish Ruby syntax over a language that eschews excessive monkey patching and dynamism like Erlang.
This sentence is specially ironic given that Erlang inherits from Prolog, which is quite different semantically from Erlang, instead of using the more tradicional ML families. Also Erlang is pretty much a very dynamic language.
I am a Haskell developer, I hate Ruby syntax and I programmed Erlang for a year. I would still choose Elixir over Erlang any day mostly because of the tooling, typeclass like polymorphism and the new abstractions (Task and Agent).
I'd wager that's because no one has written tooling to make it compelling to the common programmer. Same with release management for a long time, and hot code reloading. I'd understand if you said that basic substitution macros are nowhere close to actual AST macros, but Erlang has far more than that.
Take a look at Elixir's agents or tasks and explain how it doesn't lead to more readable and cleaner code than the GenServer equivalent in Erlang for the cases they fit.
Those are sugar. It's not like you can't define your own behaviors in Erlang. People do it all the time, there's so many good libraries that go beyond stock OTP. I should really switch an entire language because of default libraries?
This sentence is specially ironic given that Erlang inherits from Prolog, which is quite different semantically from Erlang
Only traces. The Prolog influence of Erlang is severely overrated by a lot of people these days.
Also Erlang is pretty much a very dynamic language.
It ain't no Smalltalk. The runtime is very dynamic, and the typing is loose, but the Erlang language itself not so much, which I think is a strength.
I am a Haskell developer, I hate Ruby syntax and I programmed Erlang for a year.
Good for you, chap.
Fair point.
> Those are sugar. It's not like you can't define your own behaviors in Erlang. People do it all the time, there's so many good libraries that go beyond stock OTP.
There is a very strong point in providing those as default. If Erlang didn't ship with a gen_server, we would see hundreds of different gen_server implementations and no real consensus. By providing one, all Elixir developers are familiar with it.
In a way, you could define everything Elixir provides as a sugar, after all, it runs in the same VM. Sure, an Erlang library could provide all unicode manipulation functions... but having it all sorted out for me is a great deal. The same way Erlang solves many other things which makes it attractive to many.
That leads me to...
> I should really switch an entire language because of default libraries?
No. But if it provides a really good standard library altogether (unicode, structs, enumerable, etc) with an excellent tooling and powerful abstractions (like protocols), then surely yes.
I can't comment on excellent tooling. Language-specific package managers never tend to be excellent, which is why I appreciate the limited scope of a tool like rebar.
Again, you are overvaluing a language based on the libraries it exports, rather than on its true a priori merits. Some languages are designed for intense extensibility and expressiveness, like Forth. An argument based on laundry listing abstractions to dissuade someone from using it would be rightfully dismissed as nonsense, since it is their prerogative to define the threshold of abstraction they need.
Furthermore, I've noticed that people who tend to promote languages based on the mere reductionist listing of abstractions tend to not understand those abstractions well themselves, treating it as dark wizardry.
Erlang is definitely malleable to reasonable extensibility. See Erlando which adds Miranda/Haskell-like monadic patterns to Erlang.
Also rebar3 is pretty much the same in scope as Mix (elixir tool). Which proves the point you are criticizing Elixir while using the same criteria to praise Erlang.
I am not saying Elixir is better or worse, just pointing you are extremely biased in your comments.
Elixir is semantically close to Erlang the language, and allows you to take advantage of all the great benefits of Erlang/OTP.
It's benefit is dev's productivity. Creating OTP applications and releases is simpler, and there are tools in the language (e.g. macros, polymorphism via protocols, tidier stdlib), and around it (e.g. Hex package manager, mix tool, doc tests) that make developers' life simpler.
All of this is possible in plain Erlang, but it's more cumbersome, and sometimes requires home-brewed solutions.
Notice that I'm not discussing syntax at all, because it (mostly) doesn't matter. I actually like the Prologness of Erlang. What I dislike is that some chores require more of my time and yak shaving, compared to Elixir.
For example, a lot of my work tends to revolve around working with data. Processing large batches of data, parsing (often it comes in the shape of XML), transforming, filtering, ingesting it into databases, and so on. I can do this easily in Ruby, but performance issues has driven me to use Node.js or Go for new projects. With Go it's ridiculously easy to build efficient pipes that can parallelize each step to my liking, backpressure included. It's also trivial to build small command-line tools as well as specialized daemons. I have a world of libraries (and bindings to C libraries) at my disposal: AWS, image processing, transcoding, PostgreSQL, XML, JSON, it's all there. Go is also decent at Unicode and string manipulation.
I'm not wild about Go's performance, and everything I have seen of Erlang indicates that its performance is closer to that of Ruby or Node.js. Any comments here? Whenever I need to fire up anything related to batch processing in Ruby or Node.js, things take forever. Erlang's advantage here might be that it's easier to spawn remote processes to parallelize the workload.
The Phoenix website is hosted on https://readme.io/, it seems that it uses client side rendering for posts.
Edit: Not that you can't use Phoenix without realtime capabilities, but a lot of the good stuff in Phoenix is around Channels.
Personally I've got a few books on elixir (one written by you), but I'd like to get as many resources as possible for Phoenix.
I basically said look at Ruby, it shot up because of RoR. All erlang needs is a good hype web framework.
Everybody in that room was like nope, the people can't see the power of Erlang and Erlang only solve a niche problem or that web framework isn't the answer.
Uh huh. Phoenix is evidence that programming language needs a good framework and a big user base that are hype about it. Sadly I don't see Erlang going to get momentum as Elixir and I think it's a good thing. Erlang can do it thing and Elixir can bring in more people on to the Erlang VM (BEAM).
I'd really love something built on erlang because of all the theoretical problems that just don't happen because of the way it's built.
> Phoenix is set to take on the world whether you're building APIs, HTML5 applications, or network services for native devices.
My NDC Oslo talk (linked in this thread) would answer your questions if you have the time to watch it. I give a high-level overview of Phoenix, Elixir, and the Erlang virtual machine and the virtues of how it all fits together. I'll try to get back later with a broader overview.
Sure it is, but "framework for building apps using language X which is run by virtual machine Y" is the basic pattern for JavaScript, Clojure, Scala, Java, and others. There are a lot of them, they have varying levels of integration.
Can I build a discussion forum in Phoenix? Sure, it has all the tools. Can I build it using PHP or Ruby? Sure those have tools too. Can I create an integrated IDE with my langauge and my execution environment? Sure we can do that too like Light Table.
So is it just Visual Basic all over again? Thinking of it that way is probably not conducive to polite conversation :-) but in many ways it is. We have a scripted language (Elixir), a virtual machine (Erlang), a "window" system (HTML5), and a set of APIs we can call on.
That is great, doesn't solve a new problem but solves an existing problem in a new way. And I watched Chris' talk and read the documentation, and I still don't feel like I have a good feel for why its better than what came before.
One thing it does do is allow scalability in a pretty straight-forward, integrated way.
There are lots of "new" problems with respect to changing conditions in our day to day lives. Here are a few
- Identity management across Internet and non-Internet properties
- Configuration, control, auditing, and monitoring of billions of Beacon level devices
- Zero knowledge proofs as a technique for anonymous and no repudiated purchases online
- "home" level cloud services for local and on the road implementation of always available services (mail, journaling, calendaring, Etc.)
- Reliable third party payment systems (somewhat of an old system but one that benefits from revisiting with current technology from time to time)
- Navigation and cartography tools for people in disconnected regions of the planet.
- Civil process augmentation with automation and authentication.
- Connectivity as a tax payer civic utility, without an editorial bias.
-Dynamic skills assessment for students in the presence of confounding factors (mostly remote access)
- Low friction capital markets for charitable giving (think Watsi but for everything, and with better controls than 'GoFundMe')
- Providing civic services for indigenous homeless populations.
I could go on, there are lots and lots of problems. But to be clear it isn't a criticism of Phoenix that they are not solving a new problem, the feedback was that there are lots of solutions to the general form of problem they are solving and, as feedback on this announcement, I was trying to learn from their materials how they were different (and presumptively better) than those other solutions. I'm still looking for that summary somewhere.
I couldn't find anything in the docs.
https://github.com/trenpixster/addict
https://github.com/opendrops/passport
Also here's a nice blog post that was in the elixir newsletter that may help!
An interesting choice for a name of a software project, given its history.
[1] https://www.techempower.com/benchmarks/previews/round11/
> WARNING: Preliminary data! Errors, anomalies, and other peculiarities should be expected.
We sent them a PR as their example app was doing things like html form CSRF token generation, session fetching, and heavy logging, - all for JSON apis. Phoenix has pipelines to explicitly segregate these kinds of request overhead when they aren't needed. They also used a very low database connection pool size. Hopefully they merge the PR shortly, and re-run the tests to properly represent us. See own series of benchmarks here: https://gist.github.com/omnibs/e5e72b31e6bd25caf39a#results
Congrats to the Phoenix folks; I'm pretty sure it's the first Elixir framework to hit that 1.0 milestone, and that's a pretty big deal.
Loving Erlang/Elixir/Phoenix, I really feel it is going to scale very well.
Disclaimer: My needs are currently best served by isomorphic React.
Please don't participate in the "modern web", thanks.