Larry’s Blog

It’s Not Too Late to Learn Elixir

| Comments

Elixir 是一种函数式编程语言,建立在 Erlang 虚拟机之上,作者是 Ruby 社区大名鼎鼎的 José Valim (Rails Core Team Member, Plataformatec Founder).

Dave Thomas (Programming Ruby, Agile Web Development with Rails 作者) 在 Lone Star Ruby 2013 上做过 Elixir 的演讲 Elixir: Power of Erlang, Joy of Ruby

他是这么介绍如何开始喜欢上 Elixir 的:

I came across Ruby in 1998 because I was an avid reader of comp.lang.misc (ask your parents). I downloaded it, compiled it, and fell in love. As with any time you fall in love, it’s difficult to explain why. It just worked the way I work, and it had enough depth to keep me interested.

Fast forward 15 years. All that time I’d been looking for something new that gave me the same feeling.

Then I came across Elixir, a language by José Valim, that puts a humane, Ruby-like syntax on the Erlang VM.

Now I’m dangerous. I want other people to see just how great this is. I want to evangelize. I won’t try to convert you away from Ruby. But I might just persuade you to add Elixir to your toolset.

So come along and let me show you the things that I think make Elixir a serious alternative for writing highly reliable, scalable, and performant server code.

And, more important, let me show you some fun stuff.

Elixir 是建立在 Erlang VM 之上的,改进了 Erlang 的「恶劣」语法,而又能够充分发挥 Erlang 的其他所有优点,不是不让人兴奋的。

关于 Elixir 的语法,Erlang 的作者 Joe Armstrong 是这样评价的:

What Elixir brings to the table is a complete different surface syntax, inspired by Ruby. What you might call a “non-scary” syntax, and a load of extra goodies.”

The Pipe operator: |>

1
2
import Enum
(1..10) |> map(&1*&1) |> filter(fn x -> rem(x, 2) == 0 end)

返回的结果是 [4, 16, 36, 64, 100].

|> 非常像 *nix 的管道操作符,把前一个表达式的处理结果当作参数传递给下一个表达式。所以上面的代码很好的理解:

  1. (1..10) 是 1 到 10 的区间,语法与 Ruby 相同。
  2. map 相当于 Ruby 中的 Enumerable#map,接受 (1..10)作为参数。
  3. map(&1*&1)map(fn x -> x * x end) 的语法糖,这点与 Ruby 中的语法也十分相似。
  4. map 后的结果作为参数传递给 filter, filter 保留上一个结果中的偶数。

关于 |> 操作符的好处,Joe Armstrong 举了一个例子:

假入想把一个 atom ‘abc’ 变成大写的 ‘Abc’. 在 Erlang 中不得不这么写:

1
2
 capitalize_atom(X) ->
    list_to_atom(binary_to_list(capitalize_binary(list_to_binary(atom_to_list(X))))).

或者

1
2
3
4
5
6
 capitalize_atom(X) ->
     V1 = atom_to_list(X),
     V2 = list_to_binary(V1),
     V3 = capitalize_binary(V2),
     V4 = binary_to_list(V3),
     binary_to_atom(V4).

两种实现都很 suck, 但是在 Elixir 中使用 |> 操作符来写就会变得很不错:

1
2
  X |> atom_to_list |> list_to_binary |> capitalize_binary
    |> binary_to_list |> binary_to_atom

String sigils

这个语法特性的 Ruby Feel 就更加的明显了。

1
2
%s(String with escape codes \x26 interpolation)
%S(String without escape codes and without #{interpolation})

Elixir 提供的 sigils 有:

  • %c and %C - Returns a char list;
  • %r and %R - Returns a regular expression;
  • %s and %S - Returns a string;
  • %w and %W - Returns a list of “words” split by whitespace;

Meta-programming and DSLs

既然 Elixir 拥有了类似 Ruby 的优良语法与元编程能力,那自然写 DSL 也很简单了。

1
2
3
4
5
6
7
defmodule MathTest do
  use ExUnit.Case

  test "can add two numbers" do
    assert 1 + 1 == 2
  end
end

Elixir 最新 release 的版本是 0.10.0, 虽然不确定生产环境下使用 Elixir 是否合适(至少现在不确定),但是从比较好看的语法再加上强劲的 Erlang VM 这点上来看,还是值得学习和期待的。

Hope I(we) could do something fun with Elixir.

Comments