编译模块
学习如何定义模块,并将函数组织在其中。
Elixir 编译
Elixir 始终会编译并执行源代码。elixir 和 elixirc 命令都会完成这两项操作。除了 Elixir 的文件扩展名 .ex 外,Elixir 还支持用于脚本的 .exs 文件。Elixir 对这两种文件的处理方式完全相同;唯一的区别在于用途。.ex 文件用于编译,而 .exs 文件用于脚本编写。当执行时,两种扩展名的文件都会被编译并加载到内存中,但只有 .ex 文件会将字节码写入磁盘,生成 .beam 文件。
当程序超过几行代码时,我们希望对其进行结构化。Elixir 让这变得非常简单。我们将代码拆分为命名函数,并将这些函数组织到模块中。事实上,在 Elixir 中,命名函数必须定义在模块内部。
下面我们通过一个简单的例子来说明模块的概念。在此之前,请先了解以下几点重要步骤:
-
通过
iex -S mix命令编译代码。 -
使用指定方法运行所需的模块和命名函数:
ModuleName.FunctionName。
为了在每次修改代码后都能看到终端输出,我们必须通过连续按下“Ctrl+C”两次退出 iex 会话,然后重新执行第一步。
在 iex 环境中运行 Times.double(n) 命令,其中 n 可以是任意整数。
No configuration found for ID: bbf46322107d40f4ffb8a378cfb54efe0129d6dbc11a9173f7fd586d67ccd01f
如果需要引入新的代码更改,请按以下步骤操作:
- 点击“运行”按钮重新执行代码。
- 通过连续按下“Ctrl+C”两次退出当前的
iex会话。 - 再次运行
iex -S mix命令。这将重新加载项目,并包含最新的更改。
这里我们有一个名为 Times 的模块,其中包含一个名为 double 的函数。我们通过参数的数量来标识 Elixir 函数。我们的函数接受一个参数,因此当我们传入字符串而非数字导致函数失败时,该函数会被表示为 double/1。
1iex> Times.double("cat") 2** (ArithmeticError) bad argument in arithmetic expression 3times.exs:3: Times.double/1
此时会抛出异常(ArithmeticError),并显示堆栈追踪信息。第一行告诉我们问题所在(尝试对字符串进行算术运算),第二行则指明了出错位置。注意函数名称的写法:Times.double/1。
在 Elixir 中,命名函数由其名称和参数个数共同确定。我们的 double 函数接收一个参数,因此 Elixir 将其识别为 double/1。如果我们还有一个接受三个参数的 double 函数,它就会被称为 double/3。从 Elixir 的角度看,这两个函数是完全独立的。
函数体是一个代码块
do...end 块是一种组合表达式并将其传递给其他代码的方式。它用于模块、命名函数定义以及控制结构(任何需要将代码作为一个整体处理的地方)。
然而,do...end 并不是底层语法。真正的语法如下所示:
def double(n), do: n * 2。
我们可以通过用括号包裹多行内容来向 do 传递多行代码。
1def greet(greeting, name), do: ( 2 IO.puts greeting 3 IO.puts "How're you doing, #{name}?" 4)
do...end 形式实际上只是语法糖。在编译过程中,它会被转换为 do: 形式。通常情况下,人们使用 do: 语法表示单行块,而使用 do...end 表示多行块。因此,我们的 Times 示例通常会写成如下形式:
1defmodule Times do 2 def double(n), do: n * 2 3end