Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I wouldn't say I like things over C#/.NET (I love C# and use it for mobile/desktop devel, but I've never used it for web).. but I'll list some things I like about Elixir:

Erlang's concurrency model is amazing. It's like having micro-microservices running inside your virtual machine. And you can distribute across nodes. Nothing else really has this kind of thing.

Pattern matching is beautiful and it's easy to use. Other languages have this too, so it's not like this is unique. This is one of my favorite things though; you can destructure things, you can pattern match inside a function using case, and you can pattern match on functions themselves like:

    def say("Hi"), do: IO.puts("Hello")
    def say("Bye"), do: IO.puts("Goodbye")
    def say(_msg), do: IO.puts("Where am I?")
That's basically the equivalent of having a single say() function that then does a switch/case on the input.

And a more recent addition to the language is "with". This is fantastic, it's one of my favorite things now. Usually you might have code that sets a variable from something, checks to make sure it's valid, sets another variable, checks to make sure it's valid, etc, etc... until finally you're function is ready to actually perform its purpose. Any of those checks might cause it to exit early or to switch paths. So Elixir has this "with" feature that looks sort of like this:

    def create(conn, %{"id" => group_id, "friend_id" => friend_id}) do
      with {:ok, user} <- current_user(conn, groups: [memberships: [:user, :group]]),
           {:ok, group} <- Groups.fetch_for_user(user, group_id),
           {:ok, friend} <- Friendship.fetch_friend(user, friend_id),
           {:ok, member} <- Groups.add_member(group, friend)
      do
        render(conn, "success.json", msg: msg)
      else
        {:error, msg} ->
          conn
          |> put_status(:unprocessable_entity)
          |> render("failure.json", msg: msg)
      end
    end
I love this feature. It makes code so much more readable and maintainable in my opinion.


I believe these are referred to Railway-Oriented Programming. I've seen several other examples for Elixir (incl. ones using macros), but by far this is the 'cleanest' syntax :)

Here's a similar construct in Scala:

    (for {
      user   <- currentUser(...)
      group  <- groups.fetchForUser(...)
      friend <- friendships.fetchFriend(...)
      member <- groups.addMember(...)
    } yield {
      render(...)
    }).recover {
      case e: Exception -> ...
    }


Or you could just call it what it is: a monad


"Railway-Oriented Programming" is a lot more specific than "monad".


The Scala example, yes... The Elixir one? Is it actually a Monad? I figure it's simply destructuring + pattern matching (against the value of the first tuple value, :ok or :error atom).

To expand a bit more, it's not like Scala's `Either[T, U]` where we're limited to a pair of types, I think you can return other atom values (but use :ok and :error) as a convention.

Also, there is an Elixir library I'm using that's a closer in spirit to Scala's for-comprehension called `monadex`. Example below:

    result = success(comment_params)
             ~>> fn p  -> link_reply_to_id(p)  end
             ~>> fn p  -> create_changeset(p)  end
             ~>> fn cs -> assert_changeset(cs) end
             ~>> fn cs -> insert_changeset(cs) end


Wait is `with` a guard then?


Do-notation strikes again.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: