Elixir
是函数式语言,所以函数式它的一种基本类型。
一般语法
匿名函数用 fn 创建
fn parameter-list -> body parameter-list -> body ... end
一个参数列表(圆括号可省略),一个函数体,二者通过 ->
隔开。
1 | iex> sum = fn (a, b) -> a + b end |
调用的时候1
2iex> sum.(1, 2)
3
函数模式匹配
回忆一下,Elixir
没有赋值概念,是将值和模式进行匹配。1
2
3
4iex> swap = fn {a, b} -> {b, a} end
...
iex> swap.({1, 2})
{2, 1}
一个函数,多个函数体
例如打开文件的时候,对结果进行多个匹配。1
2
3
4iex> handle_open = fn
...>{:ok, file} -> "Read data: #{IO.read(file, :line)}"
...>{_, error} -> "Error: #{:file.format_error(error)}"
...>end
_
当参数可以省略的时候,用 _
去充当一个占位。
1 | iex> handle_open.(File.open("code/hello.exs")) |
可见当文件存在,第一个参数会匹配:ok
,走第一行函数体。
文件不存在时候,匹配第二行函数体,输出错误。
函数中的函数
1 | iex> fun1 = fn -> fn -> "Hello" end end |
闭包
刚才那段代码,改造一下:1
2
3
4iex> fun1 = fn name -> fn -> "Hello,#{name}" end end
...
iex> fun1.("jack").()
"Hello,jack"
可见,内部函数调用了外部函数的变量。
变量 name
被绑定到外部函数的作用域里,当定义内部函数的时候,它继承这个作用域并将 name
的绑定值传递到里面。
这就是闭包(closure):作用域将其中的变量绑定封闭起来,并将它们打包到稍后能被保存且使用的东西上。
函数做为参数进行传递
1 | iex> fun1 = fn name -> fn -> "Hello,#{name}" end end |
另一个例子1
2iex> Enum.map [1, 2], fn elem -> elem * 2 end
[2, 4]
& 运算符
创建简短辅助的函数很普遍,所以Elixir
提供一个快捷的创建函数的方式。上面的例子,改造下:1
2iex> Enum.map [1, 2], &(&1 * 2) end
[2, 4]