Elixir匿名函数 #
一、匿名函数定义 #
1.1 基本语法 #
elixir
iex(1)> fn x -> x * 2 end
#Function<...>
iex(2)> add = fn a, b -> a + b end
#Function<...>
1.2 调用匿名函数 #
使用 . 调用匿名函数:
elixir
iex(1)> add = fn a, b -> a + b end
#Function<...>
iex(2)> add.(1, 2)
3
iex(3)> double = fn x -> x * 2 end
#Function<...>
iex(4)> double.(5)
10
1.3 多行函数 #
elixir
iex(1)> greet = fn name ->
...> message = "Hello, #{name}!"
...> IO.puts(message)
...> message
...> end
#Function<...>
iex(2)> greet.("Alice")
Hello, Alice!
"Hello, Alice!"
二、模式匹配 #
2.1 多子句匿名函数 #
elixir
iex(1)> handle = fn
...> {:ok, result} -> "Success: #{result}"
...> {:error, reason} -> "Error: #{reason}"
...> end
#Function<...>
iex(2)> handle.({:ok, "data"})
"Success: data"
iex(3)> handle.({:error, "not found"})
"Error: not found"
2.2 带守卫的匿名函数 #
elixir
iex(1)> categorize = fn
...> x when x < 0 -> :negative
...> 0 -> :zero
...> x when x > 0 -> :positive
...> end
#Function<...>
iex(2)> categorize.(-5)
:negative
iex(3)> categorize.(0)
:zero
iex(4)> categorize.(5)
:positive
2.3 列表处理 #
elixir
iex(1)> process = fn
...> [] -> "Empty list"
...> [head | tail] -> "Head: #{head}, Tail: #{inspect(tail)}"
...> end
#Function<...>
iex(2)> process.([])
"Empty list"
iex(3)> process.([1, 2, 3])
"Head: 1, Tail: [2, 3]"
三、闭包 #
3.1 捕获外部变量 #
匿名函数可以捕获定义时的外部变量:
elixir
iex(1)> prefix = "Hello, "
"Hello, "
iex(2)> greet = fn name -> prefix <> name end
#Function<...>
iex(3)> greet.("Alice")
"Hello, Alice"
3.2 闭包示例 #
elixir
iex(1)> counter = fn ->
...> count = 0
...> fn ->
...> count = count + 1
...> end
...> end
#Function<...>
iex(2)> c = counter.()
#Function<...>
iex(3)> c.()
1
iex(4)> c.()
2
3.3 工厂函数 #
elixir
defmodule Multiplier do
def create(factor) do
fn x -> x * factor end
end
end
double = Multiplier.create(2)
triple = Multiplier.create(3)
double.(5)
triple.(5)
四、捕获操作符 #
4.1 基本用法 #
使用 & 捕获函数:
elixir
iex(1)> add = &+/2
&:erlang.+/2
iex(2)> add.(1, 2)
3
iex(3)> length_func = &length/1
&:erlang.length/1
iex(4)> length_func.([1, 2, 3])
3
4.2 捕获命名函数 #
elixir
iex(1)> upcase = &String.upcase/1
&String.upcase/1
iex(2)> upcase.("hello")
"HELLO"
iex(3)> split = &String.split/2
&String.split/2
iex(4)> split.("a,b,c", ",")
["a", "b", "c"]
4.3 简写语法 #
elixir
iex(1)> double = &(&1 * 2)
#Function<...>
iex(2)> double.(5)
10
iex(3)> add = &(&1 + &2)
#Function<...>
iex(4)> add.(1, 2)
3
iex(5)> greet = &("Hello, " <> &1)
#Function<...>
iex(6)> greet.("Alice")
"Hello, Alice"
4.4 与Enum配合 #
elixir
iex(1)> Enum.map([1, 2, 3, 4, 5], &(&1 * 2))
[2, 4, 6, 8, 10]
iex(2)> Enum.filter([1, 2, 3, 4, 5], &(&1 > 2))
[3, 4, 5]
iex(3)> Enum.reduce([1, 2, 3, 4, 5], &+/2)
15
iex(4)> Enum.map(["hello", "world"], &String.upcase/1)
["HELLO", "WORLD"]
五、函数作为参数 #
5.1 高阶函数 #
elixir
iex(1)> apply_twice = fn func, value ->
...> func.(func.(value))
...> end
#Function<...>
iex(2)> double = fn x -> x * 2 end
#Function<...>
iex(3)> apply_twice.(double, 5)
20
5.2 自定义高阶函数 #
elixir
defmodule Collection do
def my_map(list, func) do
case list do
[] -> []
[head | tail] -> [func.(head) | my_map(tail, func)]
end
end
def my_filter(list, pred) do
case list do
[] -> []
[head | tail] ->
if pred.(head) do
[head | my_filter(tail, pred)]
else
my_filter(tail, pred)
end
end
end
def my_reduce(list, acc, func) do
case list do
[] -> acc
[head | tail] -> my_reduce(tail, func.(head, acc), func)
end
end
end
六、函数组合 #
6.1 简单组合 #
elixir
iex(1)> compose = fn f, g ->
...> fn x -> f.(g.(x)) end
...> end
#Function<...>
iex(2)> double = &(&1 * 2)
#Function<...>
iex(3)> increment = &(&1 + 1)
#Function<...>
iex(4)> double_then_increment = compose.(increment, double)
#Function<...>
iex(5)> double_then_increment.(5)
11
6.2 管道风格 #
elixir
iex(1)> pipe = fn f, g ->
...> fn x -> g.(f.(x)) end
...> end
#Function<...>
iex(2)> process = pipe.(
...> &String.upcase/1,
...> &String.reverse/1
...> )
#Function<...>
iex(3)> process.("hello")
"OLLEH"
七、部分应用 #
7.1 固定参数 #
elixir
iex(1)> partial_add = fn a ->
...> fn b -> a + b end
...> end
#Function<...>
iex(2)> add_five = partial_add.(5)
#Function<...>
iex(3)> add_five.(3)
8
7.2 使用捕获操作符 #
elixir
iex(1)> add_five = &(&1 + 5)
#Function<...>
iex(2)> add_five.(3)
8
iex(3)> starts_with_hello? = &String.starts_with?(&1, "Hello")
#Function<...>
iex(4)> starts_with_hello?.("Hello, World")
true
八、递归匿名函数 #
8.1 使用引用 #
elixir
iex(1)> factorial = fn
...> 0, _ -> 1
...> n, self -> n * self.(n - 1, self)
...> end
#Function<...>
iex(2)> factorial.(5, factorial)
120
8.2 Y组合子 #
elixir
iex(1)> y = fn f ->
...> (fn x -> f.(fn y -> x.(x).(y) end) end).(fn x -> f.(fn y -> x.(x).(y) end) end)
...> end
#Function<...>
iex(2)> factorial = y.(fn f ->
...> fn
...> 0 -> 1
...> n -> n * f.(n - 1)
...> end
...> end)
#Function<...>
iex(3)> factorial.(5)
120
九、函数类型 #
9.1 类型规范 #
elixir
@spec add(number(), number()) :: number()
def add(a, b), do: a + b
@spec map(list(a()), (a() -> b())) :: list(b())
def map(list, func) do
Enum.map(list, func)
end
9.2 函数类型检查 #
elixir
iex(1)> is_function(fn x -> x end)
true
iex(2)> is_function(fn x -> x end, 1)
true
iex(3)> is_function(fn x -> x end, 2)
false
十、总结 #
本章学习了:
| 特性 | 示例 |
|---|---|
| 定义 | fn x -> x end |
| 调用 | func.(arg) |
| 多子句 | fn {:ok, x} -> x; {:error, _} -> nil end |
| 闭包 | 捕获外部变量 |
| 捕获操作符 | &String.upcase/1, &(&1 * 2) |
| 高阶函数 | 函数作为参数或返回值 |
准备好学习命名函数了吗?让我们进入下一章。
最后更新:2026-03-27