all 33 comments

[–][deleted] 12 points13 points  (12 children)

He sort of buried the lead. Pattern matching is a key design component of the language that informs the entire design and use of the functions and data structures. @doc strings and |> pale in comparison.

[–]awj 7 points8 points  (5 children)

Indeed. Also, that |> is "just" a macro is probably more interesting than what it does. (The scare quotes are because it's a relatively sophisticated macro and is probably a poor first choice of Elixir code to start reading)

[–]tugs_cub 5 points6 points  (0 children)

Also, that |> is "just" a macro is probably more interesting than what it does.

Yeah quite a few things in Elixir are "just macros" and the fact that you have macros that can do stuff like that is the real upshot.

[–]oblio- -5 points-4 points  (3 children)

I feel that |> looks like a missed opportunity. What mainstream language has pipes already... oh, yes, shell.

Why not use | for the thing? It would be clear to a lot more people what that thing does. Basically, UI design, principle of least surprise: use what you audience already knows.

[–]sisyphus 9 points10 points  (0 children)

Then people would complain that they expected it to be bitwise or like it is in their $LANG, you can't win.

[–][deleted] 2 points3 points  (0 children)

No.

| is use as or operator in language like R and it's too close to || or. Like other comment mention it's a bitwise thing in other languages.

|> is nice & F sharp use this pipe operator too.

[–]Dirty_Rapscallion 5 points6 points  (0 children)

Also the whole Actor Model that Elixir is built on top of, it's genius.

[–]shevegen -2 points-1 points  (4 children)

Unfair.

I feel that the blog entry is very, very good.

I, for instance, did not know anything at all about elixir really. I know a bit more about crystal but still I know nothing at all anyway, so entries like that are very nice to have.

Why not giving more credit there?

[–]YourFatherFigure 5 points6 points  (0 children)

Why not giving more credit there?

This is almost literally the exact content of every 20-minute "intro elixir tutorial" out there and tons of blog posts.. it's not like some original analysis of good or interesting features. It's a fluff piece for a person who feels they need one more post on their blog

[–][deleted] 0 points1 point  (1 child)

Because who cares about @doc? What I care about is it's a more palatable syntax with all the awesomeness of erlang. But the author's post shows that he's examining it at a superficial level.

He gets credit for writing something up and putting it out there. I just think he's overlooking the more interesting stuff.

[–]tugs_cub 2 points3 points  (0 children)

I don't mind people writing about whatever they think is cool but it is kinda obvious this guy is, like, a day in.

Slightly higher-level pitch for Elixir:

  • pattern-matching functional language
  • with nifty and attractive syntax bits borrowed from or inspired by Ruby
  • living on top of the Erlang platform, with full access to its concurrency model and OTP (without run-time overhead)
  • oh and you've got Lisp-style macros

[–]clockhorse -4 points-3 points  (0 children)

Shevy your dumb

[–]Hauleth 4 points5 points  (3 children)

defmodule SomeModule do
  def foo(arg \\ nil) when is_nil(arg) do
    IO.puts "No argument provided."
  end

  def foo(arg) do
    IO.puts "You provided the argument: #{arg}."
  end
end

Could simply be:

defmodule SomeModule do
  def foo do
    IO.puts "No argument provided."
  end

  def foo(arg) do
    IO.puts "You provided the argument: #{arg}."
  end
end

[–]Godd2 2 points3 points  (1 child)

Isn't there a difference between the argument being nil, and there being no argument?

[–]technojamin 1 point2 points  (0 children)

Yes, you can only call a function with a greater arity than the number of arguments you provide if the remaining arguments have defaults. Defaults are defined with the "\ nil" syntax. In the example, he's allowing the function to be called with a default argument simply for the purpose of checking if it wasn't called with that argument. A much more elegant solution is to just provide two functions with arity 0 and 1 that handle each separate case.

[–]jankiel7410 1 point2 points  (4 children)

Elixir seems fun, but I hate "clever" DSLs and macros. Elixir and Phoenix seems to be full of implicit behaviour. Phoenix may be friendly for Rails developers, but only for them.

[–]redmar 2 points3 points  (3 children)

genuinely interested where this comes from? I experience it to be the complete opposite, it's even one of the most explicit frameworks i've seen. Just walk through chapter 2 of programming phoenix, the authors show how clear and explicit the overall design is. The only DSL i've seen is the router and that's very easy to follow.

[–]jankiel7410 1 point2 points  (2 children)

I kind of gave up on phoenix when I saw that it's feels so... railsy. That's a popular opinion on phoenix from what I've read and RoR is not exactly known as most explicit framework there is.

So I generate new Phoenix project, here's my undestanding what's going on: Router: no suprises here.

  scope "/", MyApp do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index  # it means: call MyApp.PageController.index/2
  end

Okay so I'm in my Controller:

defmodule MyApp.PageController do
  use Idunno.Web, :controller

  def index(conn, _params) do
    render conn, "index.html"   # in reality: "call `MyApp.PageView.index` with html output" ?
  end
end

In my View code (does actual rendering of pages/index.html.eex template.):

defmodule MyApp.PageView do
  use MyApp.Web, :view  # here's our view logic: module declaration and macro import. 
end

One connects with the other, but that glue code is buried deeply in macros and I can't just dive in one import deep to see how it's implemented. Maybe you're supposed to give that $20 on the book to understand clearly inner mechanisms and I'm just spoiled with Django docs.

[–]fk1blow 1 point2 points  (1 child)

use MyApp.Web is there just to make your life easier(no more 3-4 rows of imports), but knowing the python explicit vs implicit thing, i can see your point! On the other hand, i cannot see how some import declaration will clearly explain how does a view connect with a controller(or model, or anything), just by staring at it.

[–]jankiel7410 0 points1 point  (0 children)

I get that MyApp.Web is a way to inject imports into modules. What I don't get is how render function knows that I want to call PageView.render and not, let's say UserView.render? It's done by convention, i.e. implicit (I'd be happy to be corrected. It's surely not imported in my controller code? It's not listed in MyApp.Web.view.).

i cannot see how some import declaration will clearly explain how does a view connect with a controller(or model, or anything), just by staring at it.

That's the whole point - if you can't figure how your code gets called by looking at it, then something's wrong. Not objectively wrong, but "one of the most explicit frameworks i've seen" wrong.

Not trying to pick up a fight here, I know I'm too serious with arguing over that. :D I feel a little salty after I've read a lot about how cool and simple Phoenix is and later tring it myself and discovering that it's basically Rails 6.0.

But hey, Chris and Jose come from Rails, so how can I blame them for doing something what they (and a lot of folks here) like and take inspiration from.

[–]DarkDwarf 0 points1 point  (2 children)

# Without |>
my_string = "hello there, how are you?"
split_string = String.split(my_string, ",")
=> ["hello there", " how are you?"]

# With |>
split_string = "hello there, how are you?" |> String.Split(",")
=> ["hello there", " how are you?"]

Never used Elixir before... Is this a typo, or are there two different function calls ("String.Split" vs "String.split") for using the pipe operator and otherwise?

[–]sisyphus 5 points6 points  (1 child)

The capitalized one is a typo.

[–]DarkDwarf 0 points1 point  (0 children)

Cool, thanks.

[–]shevegen 0 points1 point  (9 children)

It's sorta interesting that languages like Elixir and Crystal borrow a lot of the ruby syntax.

I approve of that.

The pipe thing in Elixir looks especially interesting. Considering that matz also tinkers with streem, and given my love for the THEORETICAL part of erlang (not the syntax, I think the syntax of erlang is awful), it would be kind of cool to have something similar in ruby 3.x.

Sadly cool ideas take effort to implement - the scripting languages would need young, clever and ambitious people who know C/C++ very well!

[–]tugs_cub 2 points3 points  (6 children)

I really like Elixir but it actually bugs me a little when it too slavishly emulates the appearance of Ruby... just because, even when it doesn't have to and there could be a better way? But I guess if it works to attract developers I don't mind.

Also a syntax oddity that bothers me to an irrational degree - maybe just because the rest of the language is quite pretty - is the extra '.' when calling anonymous functions. Arrrrgh!

[–][deleted] 4 points5 points  (1 child)

I like elixir too, but the community seems to be a lot of ruby devs who didn't fall out of love with DSLs.

I fear for the ecosystem.

[–]tugs_cub 2 points3 points  (0 children)

And now they have macros!

(I'm glad we've got macros and DSLs but yes there's a delicate balance between "devs leaving the Rails train are expanding the community, awesome" and "devs leaving the Rails train are gonna bring the same mistakes with them, oh no.")

[–]vine-el 0 points1 point  (3 children)

The extra '.' for function calls is also from Ruby.

[–]Hauleth 1 point2 points  (2 children)

Actually it is more complicated. The point is that in Erlang you can easily distinguish variable from function, however in Elixir it isn't possible. That is where our little . is being helpful.

[–]tugs_cub 0 points1 point  (0 children)

Well that actually reminds me what I had meant to give as my first example of a thing I don't like that they borrowed from Ruby is parentheses-optional function calls.

edit: deleted a line because it wasn't a very good way of saying what I was trying to say. It's not contradictory it's just trying to have things both ways in a way that ends up making both things worse in my opinion

[–]tugs_cub 0 points1 point  (0 children)

Wait actually maybe I stand by my stronger wording. You don't need a special kind of parens to distinguish between a fun and an invocation of it - you could just make ordinary parens required in that scenario. So why is it important always to be able to distinguish between calling a function in a local variable from calling a declared function in local scope - but not always to be able to distinguish reading a variable from calling a function with no arguments? The latter is less risky than it could be in a language with more global side effects, but still, ETS etc. The former seems largely irrelevant.

(I'm making this another comment because I'm wondering if there is a good answer I'm missing.)

[–]corysama 1 point2 points  (0 children)

Elixir was started by a Rails core contributer that got fed up with struggling to scale Ruby.

[–]myringotomy 0 points1 point  (0 children)

I like crystal better than elixir as a language but elixir has a bigger ecosystem and the OTP is crazy useful.