It seems that many Elixir people come from Ruby. One thing we should be wary of is making shallow ports of Ruby concepts into Elixir, when there's much more elegant approaches available. We, software engineers, have a tendency of doing this: for example, there's a whole bucketload of C# libraries that have Java roots (NHibernate, Spring.NET), and every single one of them is a bloated piece of nonsense that doesn't make good use of C#'s strengths. We should avoid making Elixir a Ruby-on-Erlang when it has the potential to be so much more.
I haven't figured out yet to what extent Phoenix does this, but this blog post highlights some things that make me wonder.
For instance, the router confuses me. Is there any point in making an explicit router over just splitting the URL by "/" into a list and then just pattern matching on that?
e.g.
def get(["users", user], _params) do
# show stuff
end
def post(["users"], _params) do
# store stuff
end
def get([], _params) do
# show root page
end
Is Phoenix's routing somehow more powerful than that, for reasons that I'm missing, or is it just a Rails-ism blatantly ported over to Elixir?
Phoenix creator here. Please take a look at my ElixirConf presentation where I exactly address your concerns. We're very much not out to replicate Rails and we are leveraging Elixir's strengths. As Dave Thomas said "Why replicate when you can innovate?". I very much agree. Our realtime Channel layer shows this off. That said, we have borrowed a few ideas from Rails where they make sense. I think Rails got a lot more right than it got wrong, but our goals are to go well beyond and redefine what you think of as a "web framework" traditionally. We're aiming for a "highly connected web framework" for devices, whether that's your browser, iPhone, Android, or smart toaster. For example, we already have a native Swift client for our Channel layer. With respect to the Router example, our Router DSL does a number of things like defining named route helpers, i.e.:
`Router.users_path(:show, 123)`
We also have a `resources` macro similar to Rails style that wires up half a dozen or so resftul endpoints that you'd otherwise have to roll by hand. This would be particularly tedious in your example once you started nesting resources. The Router also serves as the entry point to the Plug middleware stack where we wire up some essential middleware and connection metadata.
> We should avoid making Elixir a Ruby-on-Erlang when it has the potential to be so much more.
I agree and share the enthusiasm. However, I feel like Elixir gets a bad rap just because how similar it looks to Ruby. I feel that other languages, such as HN's current darling Go, and Node.js actually have way more Ruby/Railsism libraries than Elixir does. In Go, there are hundreds of libraries with the tag line "Like <some Ruby library> but for Go!". The same goes for Node.js, but that number is probably in the thousands. In Rust, someone has actually tried to port ActiveSupport to Rust!
Syntax aside, the only influences Ruby has on Elixir in current day is the virtue of creating joy to use tools. Mix is a great example of this. Which is great, because that is by far Ruby's greatest strength and is the only Ruby influence I would want in Elixir, having been a Ruby user for many years.
When you start to get familiar with Elixir, you realize it is far more influenced by Lisp/Clojure and Erlang than it is Ruby.
We had a lot of conversations about this and it was a somewhat common topic during ElixirConf (http://www.confreaks.com/events/elixirconf2014). On my keynote I addressed exactly your concerns: it is fine to do "X in Elixir", which is a very helpful learning exercise, but remember to revisit it later, otherwise you will have a project that misuses or does not fully uses this new environment.
Dynamo (https://github.com/dynamo/dynamo) is such an example. It was one of the first web frameworks that showed up for Elixir and it got a lot of things wrong. However, out of the lessons learned, we got:
* The configuration layer that comes with Elixir. Elixir has the concept of applications (the same as Erlang/OTP applications) which you can be stopped and started as a unit. So the whole mechanism on how you define applications and configure them is defined by the language/runtime and consequently that is one area where Phoenix is considerably different than Rails.
* I absolutely hated the view layer in Dynamo (which attempted to be too Rails like and did not fit Elixir). Chris got the lessons learned from that and provided an absolute great view layer for Phoenix, where you have the concept of views (modules) and templates (embedded into those modules). Dispatching to views is done with pattern matching (similar to your example above). There aren't any global helpers and the views are easily testable in isolation.
* Plug (https://github.com/elixir-lang/plug) also came out of Dynamo. It has the same goals as Rack (because you can't really diverge from the goals): a specification for web servers and an API for connecting applications. However, implementation wise, it is very different than Rack. Rack applications usually build on top of a middleware stack which receives a request environment, passing through all layers, and then returns a response that once again goes through all layers. This approach is what makes Rack uncomfortable for chunking, connection upgrades and so on. In Plug, the plug stack is one-way, you only get the connection (instead of a request and response) because we assume a response can be sent through the connection at any point during the stack (disclaimer: I am both Rack and Plug committer).
The list could go on. :) Our build tool, Mix (http://elixir-lang.org/docs/mix), is inspired on Clojure's lein. The most used database layer, Ecto (https://github.com/elixir-lang/ecto), borrows a lot from LINQ (hard to have an ORM when you don't have objects!). There are even some other smaller examples in Phoenix like the current attempts to remove the singular/plural nouns that we see a lot in Rails and, in my opinion, causes a lot of confusion.
I really appreciate your attitude. You are really inspirig people like me to understand it is okay to make mistakes :). Also, every mistake teaches you something. Learn from your mistakes and keep building things that matters :).
Cool, thanks for that bit of history. I did not know about Dynamo, and I'm impressed by how willingly it was dismissed when learned lessons arrived. The early-adopting C# guys who ported Hibernate over weren't so insightful.
Great that you're pushing this attitude! I see that maybe I worry too much.
> We should avoid making Elixir a Ruby-on-Erlang when it has the potential to be so much more.
Elixir is fool-proof from turning it into a "Ruby on Erlang" simply because it embraces and improves on Erlang's programming model. Some libraries are ported over from Ruby. But there are also libraries ported from other languages and libraries that have been written for Elixir specifically.
Just a heads up: please don't make hasty generalisations based on a single project you've seen.
When I wrote "we should avoid making Elixir a Ruby-on-Erlang", i meant exactly that. I didn't mean the sugar-coated American oh my god how can I say this without being direct version of "we're making Elixir a Ruby-on-Erlang and this has to stop".
Sorry if you were offended, but I think you're reading more in my comment than there is.
Elixir is young enough that it can go many directions and it depends on the early libraries and frameworks what that will be, and we should be able to discuss that. I ended my comment with a question precisely because I don't actually know enough about Phoenix to judge it.
I wasn't implying anything beyond the quoted phrase. My last remark was targeted at anyone reading the comment, I didn't mean to sound condescending towards you.
I don't share your belief that early libraries and frameworks have the potential to override Elixir's broad domain. In other words, even if there will be a widely popular library/framework for Elixir, it won't automatically negate its other strength or fitness for a wide range of uses.
During the recently held ElixirConf we've seen it used in a telecom company, also powering game servers, distributed robots, and hobby projects like an elevator controller and command-line applications. The community already has a diverse set of interests and many of us will be pushing the adoption in our respective areas of interest.
In any case, our best effort today would be to continue hacking and having fun with Elixir, and at the next year's conference we'll be able to see in which direction the trends go.
I realize now it sounds as if Erlang got something wrong and Elixir got it right instead. That's not what I wanted to say.
Elixir semantics is very close to Erlang's, but it also has things beyond what Erlang can offer as easily: macros, protocols, comprehensions with any kind of enumerable as a generator.
Of course, the core facilities provided by the runtime system are left unchanged: concurrency primitives, functional semantics, distribution, error handling (Elixir has slightly different conventions, but the idea of "letting it crash" remains). And in OTP land there are quite a few additions that simply make OTP more "elixirish" (like getting a lazy stream of events from GenEvent).
For those curious about the realtime layer in Phoenix, I have a screencast where we live code a Phoenix chat app. We've added a View layer since the recording, so ignore the rendering hack:
Has anyone used both Phoenix and Chicago Boss in anger (to at least some extent)? It'd be great to see a comparison between the two.
I'll start by saying that Phoenix seems specifically built for Elixir, while Chicago Boss appears to be an Erlang framework which works fine with Elixir after a minimal amount of initial configuration upfront.
It seems that many Elixir people come from Ruby. One thing we should be wary of is making shallow ports of Ruby concepts into Elixir, when there's much more elegant approaches available. We, software engineers, have a tendency of doing this: for example, there's a whole bucketload of C# libraries that have Java roots (NHibernate, Spring.NET), and every single one of them is a bloated piece of nonsense that doesn't make good use of C#'s strengths. We should avoid making Elixir a Ruby-on-Erlang when it has the potential to be so much more.
I haven't figured out yet to what extent Phoenix does this, but this blog post highlights some things that make me wonder.
For instance, the router confuses me. Is there any point in making an explicit router over just splitting the URL by "/" into a list and then just pattern matching on that?
e.g.
Is Phoenix's routing somehow more powerful than that, for reasons that I'm missing, or is it just a Rails-ism blatantly ported over to Elixir?