Elixir Lang 简介

已发表: 2015-02-27

Elixir 编程语言简介(以及我为什么喜欢它)

几个月前我写了一篇文章向你介绍 Golang,以及为什么我如此喜欢它。 虽然我确实仍然喜欢它,但最近我一直在玩一种新的语言; 长生不老药。 我买了《Programming Elixir》这本书,并一直在关注它。 我已经开始爱上 Elixir,并希望在本文中向您展示原因。

几年前我在 Couchbase 工作时,我对 Erlang 和分布式系统产生了浓厚的兴趣。 对我来说,Erlang 令人困惑。 当我看到 Elixir 时,我立即知道我做的是好事。 Elixir 被详细描述为一种运行在 Erlang VM 之上的函数式并发语言。

我听过很多次,有人说 Elixir 是 'Ruby for Erlang' 之类的。这个理论并不完全错误,但实际上,它主要只是 Elixir 的语法受 Ruby 影响,因为它不共享许多相同的编程结构。 当然,它在方式上与 Erlang 类似,它构建在 Erlang VM 之上,让我们可以直接访问原生的 Erlang 原语。

无论如何,毫不犹豫地,让我们潜入并继续使用一些 Elixir。

安装

如果你在 OSX 上运行,安装就像使用 Homebrew 一样简单:
~ brew update
~ brew install erlang
~ brew install elixir

完成此操作后,您应该能够运行:

~ elixir -v
> Elixir 1.0.2

现在 Elixir 已正确安装,我们可以打开一个Interactive Elixir并尝试一些基本的常用类型。

Elixir 的种类

通过输入启动交互式 Elixir REPL
> iex

变量:

iex(1)> name = "rbin"
#=> "rbin"

原子:

在 Elixir 中,Atom 是一个常量,它的名字就是它自己的值。
iex(2)> :this_is_an_atom
#=> :this_is_an_atom
iex(3)> :my_atom == :atom
#=> false

元组:

我们使用花括号符号来定义元组。 在 Elixir 中,元组立即存储在内存中,这意味着获取元组的大小或访问元组元素的速度很快,但更新或添加元素的成本很高,因为它需要将整个元组复制到内存中。

iex(4)> tuple = {:hello, "world"}
#=> {:hello, "world"}
iex(5)> elem(tuple, 1)
#=> "world"

列表:

在 Elixir 中,列表作为链表存储在内存中。 我们可以通过添加元素来简单地更新列表,但是添加元素的成本更高,因为我们需要遍历整个列表来计算它的大小。

iex(8)> list = [1, 2, :atom]
#=> [1, 2, :atom]
iex(9)> ["string"] ++ list
#=> ["string", 1, 2, :atom]
iex(10)> list ++ [31]
#=> [1, 2, :atom, 31]

有非常有用的内置函数可用于列表,包括获取列表的头部和尾部。

iex(11)> hd(list)
#=> 1
iex(12)> tl(list)
#=> [2, :atom]

匿名函数:

在 Elixir 中,函数是一等公民,这意味着我们可以将函数作为参数传递给其他函数。 下面,我们将定义一个名为add的变量,其中包含一个函数,然后我们将把它作为参数传递给is_function/1 func

iex(14)> add = fn a, b -> a + b end
#Function<12.90072148/2 in :erl_eval.expr/5>

iex(15)> add.(13, 31)
#=> 44

iex(16)> is_function(add)
#=> true

组织我们的项目(混合)

Elixir 附带了一个名为 Mix 的超级有用的工具。 Mix 是一个构建工具,它使我们能够非常轻松地生成、组织、编译和测试我们的项目。 它还使我们可以轻松管理依赖项。 (总是一个敏感的话题!)要使用 Mix 创建一个新项目,我们只需执行以下操作:
~ mix new myapp --module MyApp
这将创建一个名为myapp的目录,其中包含一些文件。 它还将在lib/myapp.ex中定义一个模块MyApp
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/myapp.ex
* creating test
* creating test/test_helper.exs
* creating test/myapp_test.exs


Your mix project was created successfully.
You can use mix to compile it, test it, and more:

cd myapp
mix test

如我们所见,我们获得了基本项目结构所需的所有文件。 我认为这是 Elixir 附带的更好的功能之一。 拥有项目管理工具非常有用,并且可以节省大量时间。

文件mix.exs是用于配置我们的项目和管理依赖项等的主要文件。我们得到一个test/folder ,我们可以在其中为我们的项目编写非常类似于 ruby​​ 的测试。 我们当然会得到一个lib/folder ,其中包含我们项目的源文件。 如果我们在我们的应用程序上运行混合测试,我们会得到以下结果:
$ mix test
Compiled lib/myapp.ex
Generated myapp.app
.

Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 tests, 0 failures

Randomized with seed 543313

并发

与 Erlang 非常相似,Elixir 使用“Actor”模型进行并发。 我们所有的代码都在Processes中运行,并且这些进程彼此隔离。 我们可以通过生成进程并在它们之间发送接收消息来在 Elixir 中创建完全并发的程序。

在 Elixir 中,我们使用spawn函数启动进程,该函数将另一个函数作为参数。

iex(1)> spawn(fn -> IO.puts 1 + 1 end)
#=> 2
#PID<0.55.0>

如您所见,我们生成了一个输出 1 + 1 的进程,并且还返回了它的进程 ID。 返回此进程 ID 很有用,因为我们可以将它分配给一个变量,并使用它向进程发送消息。 在我们这样做之前,我们需要创建一个接收机制来获取我们发送给进程的消息。 (我们可以在我们的交互式 Elixir会话中逐行执行此操作。)

完成后,我们可以创建一个评估area_loop的进程,并将其分配给pid

pid = spawn(fn -> Geometry.area_loop() end)
#=> #PID<0.40.0>

然后我们可以向pid发送我们预定义的代码将匹配的消息,这取决于它是接收:rectangle原子还是:circle原子。

send pid, {:rectangle, 2, 3}
#=> Area = 6
# {:rectangle,2,3}

send pid, {:circle, 2}
#=> Area = 12.56000000000000049738
# {:circle,2}

我们可以使用Process.alive 查看进程是否仍在运行? 功能。

Process.alive?(pid)
#=> false

结论

我们甚至还没有在这个博客中触及表面。 Elixir 中有很多令人惊叹的功能,希望您继续亲自检查一下。 我在下面列出了一些学习资源来帮助你,但在你开始深入研究之前,这里有一些我个人最喜欢的关于 Elixir 的东西:

  • 它很容易掌握,具有类似ruby​​ 的语法和类似 Erlang 的原语
  • 它背后有一个很棒的社区
  • 它的并发模型对我来说既熟悉又非常强大
  • 混合是天赐之物,可以节省大量时间
  • Elixir 鼓励我们记录一切
  • 它使构建分布式应用程序成为一个不那么混乱的战场
  • 我可以看到 Elixir 有很长的路要走。

资源

在我短暂学习 Elixir 的过程中,我发现一些资源非常有用:

  • http://elixir-lang.org/getting-started/introduction.html
  • https://pragprog.com/book/elixir/programming-elixir
  • https://teamgaslight.com/blog/the-best-resources-for-learning-elixir
  • http://exercism.io

*出去喝一口长生不老药! –@rbin *