使用defmodule
宏定义模块,使用def
宏定义函数
iex> defmodule Math do
...> def sum(a, b) do
...> a + b
...> end
...> end
iex> Math.sum(1, 2)
3
编译
如果math.ex
文件有以下代码:
defmodule Math do
def sum(a, b) do
a + b
end
end
可以使用elixirc
来进行编译:
$ elixirc math.ex
执行后,会在该文件所在的目录生成一个Elixir.Math.beam
字节码文件
再次打开iex
,即可执行里面的函数
iex> Math.sum(1, 2)
3
在
iex
中使用c 文件名
可以直接调用模块里的函数
iex> c "math.ex"
[Math]
iex> Math.sum(1, 2)
3
elixir 项目通常包括三个目录:
-
ebin - 包含编译好的字节码文件
-
lib - 包含 elixir 代码 (通常是 .ex 文件)
-
test - 包含测试代码 (通常是 .exs 文件)
脚本模式
exs
文件用于脚本模式,它不会生成.beam
文件。但两种文件在执行时都可以将其模块编译并加载到内存中
defmodule Math do
def sum(a, b) do
a + b
end
end
IO.puts Math.sum(1, 2)
这样执行它:
$ elixir math.exs
命名函数
在模块中,使用def/2
定义函数,使用defp/2
定义私有函数。
函数声明支持哨兵子句和多个子句,这个特性可以替代其他语言的 if else
defmodule Math do
def zero?(0) do
true
end
def zero?(x) when is_integer(x) do
false
end
end
?
是一种命名规范,返回布尔值的函数以?
结尾,参照文档
跟if
宏类型,命名函数也支持do:
和do/end
这两种模式
可以在一行中使用do:
,在多行中使用do/end
默认参数
参数设置默认值可以用 argument \\ value
语法:
defmodule Greeter do
def hello(name, language_code \\ "en") do
phrase(language_code) <> name
end
defp phrase("en"), do: "Hello, "
defp phrase("es"), do: "Hola, "
end
iex> Greeter.hello("Sean", "en")
"Hello, Sean"
iex> Greeter.hello("Sean")
"Hello, Sean"
iex> Greeter.hello("Sean", "es")
"Hola, Sean"
函数捕获
函数捕获允许将命名函数分配给变量,调用方式跟调用匿名函数一样。
defmodule Math do
def zero?(0), do: true
def zero?(x) when is_integer(x), do: false
end
对于上面的函数,可以使用&Math.zero?/1
分配给变量fun
,调用方式跟匿名函数一样,使用fun.(0)
调用
iex> Math.zero?(0)
true
iex> fun = &Math.zero?/1
&Math.zero?/1
iex> is_function(fun)
true
iex> fun.(0)
true
捕获语法可以作为创建函数的快捷方式:
iex> fun = &(&1 + 1)
#Function<6.71889879/1 in :erl_eval.expr/5>
iex> fun.(1)
2
iex> fun2 = &"Good #{&1}"
#Function<6.127694169/1 in :erl_eval.expr/5>
iex)> fun2.("morning")
"Good morning"
&1
表示传递给函数的第一个参数,上面的&(&1 + 1)
等同于fn x -> x + 1
从模块捕获一个函数,可以使用&Module.function()
iex> fun = &List.flatten(&1, &2)
&List.flatten/2
iex> fun.([1, [[2], 3]], [4, 5])
[1, 2, 3, 4, 5]
&List.flatten(&1, &2)
等同于fn (list, tail) -> List.flatten(list, tail)
匿名函数
匿名函数可以内联创建并由关键字fn
和end
分隔:
iex> add = fn a, b -> a + b end
iex> add.(1, 2)
3
iex> is_function(add)
true
iex> is_function(add, 2) # 检查是否是带两个参数的函数
true
iex> is_function(add, 1)
false
管道操作符
管道操作符 |>
把前一个表达式的结果作为第一个参数传递给后一个表达式
foo(bar(baz(new_function(other_function()))))
# 等价于
other_function() |> new_function() |> baz() |> bar() |> foo()
最佳实践:如果函数的参数大于 1,一定要使用括号,便于理解
# 检查尾部字符串
iex> "elixir" |> String.ends_with?("ixir")
true