Elixir高阶函数 #
一、高阶函数概念 #
1.1 什么是高阶函数 #
高阶函数是指接受函数作为参数或返回函数的函数。
1.2 Elixir中的高阶函数 #
elixir
iex(1)> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]
iex(2)> Enum.filter([1, 2, 3, 4, 5], fn x -> x > 2 end)
[3, 4, 5]
iex(3)> Enum.reduce([1, 2, 3, 4, 5], 0, fn x, acc -> acc + x end)
15
二、管道操作符 #
2.1 基本用法 #
管道操作符 |> 将左边表达式的结果作为右边函数的第一个参数:
elixir
iex(1)> "hello" |> String.upcase()
"HELLO"
iex(2)> "hello" |> String.upcase() |> String.reverse()
"OLLEH"
2.2 等价形式 #
elixir
String.reverse(String.upcase("hello"))
"hello" |> String.upcase() |> String.reverse()
2.3 链式处理 #
elixir
defmodule DataProcessor do
def process(data) do
data
|> Enum.filter(&valid?/1)
|> Enum.map(&transform/1)
|> Enum.sort()
|> Enum.take(10)
end
defp valid?(item), do: item != nil
defp transform(item), do: String.upcase(item)
end
2.4 与多参数函数 #
elixir
iex(1)> [1, 2, 3] |> Enum.map(&(&1 * 2))
[2, 4, 6]
iex(2)> "a,b,c" |> String.split(",")
["a", "b", "c"]
iex(3)> [1, 2, 3] |> Enum.join("-")
"1-2-3"
三、Enum模块 #
3.1 映射函数 #
map #
elixir
iex(1)> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]
iex(2)> Enum.map([1, 2, 3], &(&1 * 2))
[2, 4, 6]
map_every #
elixir
iex(1)> Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2, fn x -> x * 2 end)
[2, 2, 6, 4, 10, 6, 14, 8, 18, 10]
flat_map #
elixir
iex(1)> Enum.flat_map([1, 2, 3], fn x -> [x, x * 2] end)
[1, 2, 2, 4, 3, 6]
3.2 过滤函数 #
filter #
elixir
iex(1)> Enum.filter([1, 2, 3, 4, 5], fn x -> x > 2 end)
[3, 4, 5]
iex(2)> Enum.filter([1, 2, nil, 4, nil], & &1)
[1, 2, 4]
reject #
elixir
iex(1)> Enum.reject([1, 2, 3, 4, 5], fn x -> x > 2 end)
[1, 2]
filter_map #
elixir
iex(1)> Enum.filter_map([1, 2, 3, 4, 5], fn x -> x > 2 end, fn x -> x * 2 end)
[6, 8, 10]
3.3 归约函数 #
reduce #
elixir
iex(1)> Enum.reduce([1, 2, 3, 4, 5], 0, fn x, acc -> acc + x end)
15
iex(2)> Enum.reduce([1, 2, 3, 4, 5], fn x, acc -> acc + x end)
15
iex(3)> Enum.reduce([1, 2, 3, 4, 5], [], fn x, acc -> [x | acc] end)
[5, 4, 3, 2, 1]
reduce_while #
elixir
iex(1)> Enum.reduce_while([1, 2, 3, 4, 5], 0, fn x, acc ->
...> if x < 4, do: {:cont, acc + x}, else: {:halt, acc}
...> end)
6
3.4 查找函数 #
find #
elixir
iex(1)> Enum.find([1, 2, 3, 4, 5], fn x -> x > 2 end)
3
iex(2)> Enum.find([1, 2, 3, 4, 5], fn x -> x > 10 end)
nil
iex(3)> Enum.find([1, 2, 3, 4, 5], 0, fn x -> x > 10 end)
0
find_value #
elixir
iex(1)> Enum.find_value([1, 2, 3, 4, 5], fn x -> if x > 2, do: x * 2 end)
6
find_index #
elixir
iex(1)> Enum.find_index([1, 2, 3, 4, 5], fn x -> x > 2 end)
2
3.5 排序函数 #
sort #
elixir
iex(1)> Enum.sort([3, 1, 4, 1, 5, 9])
[1, 1, 3, 4, 5, 9]
iex(2)> Enum.sort([3, 1, 4, 1, 5, 9], :desc)
[9, 5, 4, 3, 1, 1]
sort_by #
elixir
iex(1)> users = [%{name: "Alice", age: 30}, %{name: "Bob", age: 25}]
[%{age: 30, name: "Alice"}, %{age: 25, name: "Bob"}]
iex(2)> Enum.sort_by(users, & &1.age)
[%{age: 25, name: "Bob"}, %{age: 30, name: "Alice"}]
3.6 分组函数 #
chunk_every #
elixir
iex(1)> Enum.chunk_every([1, 2, 3, 4, 5, 6], 2)
[[1, 2], [3, 4], [5, 6]]
iex(2)> Enum.chunk_every([1, 2, 3, 4, 5], 2, 1)
[[1, 2], [2, 3], [3, 4], [4, 5]]
group_by #
elixir
iex(1)> Enum.group_by(["apple", "banana", "apricot"], fn x -> String.first(x) end)
%{"a" => ["apple", "apricot"], "b" => ["banana"]}
split #
elixir
iex(1)> Enum.split([1, 2, 3, 4, 5], 3)
{[1, 2, 3], [4, 5]}
iex(2)> Enum.split_with([1, 2, 3, 4, 5], fn x -> x > 2 end)
{[3, 4, 5], [1, 2]}
3.7 聚合函数 #
elixir
iex(1)> Enum.sum([1, 2, 3, 4, 5])
15
iex(2)> Enum.product([1, 2, 3, 4, 5])
120
iex(3)> Enum.min([3, 1, 4, 1, 5, 9])
1
iex(4)> Enum.max([3, 1, 4, 1, 5, 9])
9
iex(5)> Enum.min_max([3, 1, 4, 1, 5, 9])
{1, 9}
iex(6)> Enum.count([1, 2, 3, 4, 5])
5
iex(7)> Enum.count([1, 2, 3, 4, 5], fn x -> x > 2 end)
3
3.8 成员检查 #
elixir
iex(1)> Enum.member?([1, 2, 3, 4, 5], 3)
true
iex(2)> Enum.any?([1, 2, 3, 4, 5], fn x -> x > 3 end)
true
iex(3)> Enum.all?([1, 2, 3, 4, 5], fn x -> x > 0 end)
true
iex(4)> Enum.empty?([])
true
四、Stream模块 #
4.1 惰性序列 #
Stream是惰性的,只在需要时计算:
elixir
iex(1)> stream = Stream.map(1..100_000, &(&1 * 2))
#Stream<[enum: 1..100000, funs: [#Function<...>]]>
iex(2)> Enum.take(stream, 5)
[2, 4, 6, 8, 10]
4.2 无限序列 #
elixir
iex(1)> Stream.cycle([1, 2, 3]) |> Enum.take(10)
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
iex(2)> Stream.iterate(1, &(&1 * 2)) |> Enum.take(10)
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
iex(3)> Stream.unfold(0, fn n -> {n, n + 1} end) |> Enum.take(5)
[0, 1, 2, 3, 4]
4.3 链式操作 #
elixir
iex(1)> 1..100_000
...> |> Stream.map(&(&1 * 2))
...> |> Stream.filter(&(rem(&1, 3) == 0))
...> |> Enum.take(5)
[6, 12, 18, 24, 30]
4.4 文件处理 #
elixir
"large_file.txt"
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Stream.filter(&(String.length(&1) > 0))
|> Enum.take(100)
五、列表推导式 #
5.1 基本语法 #
elixir
iex(1)> for x <- [1, 2, 3], do: x * 2
[2, 4, 6]
5.2 多生成器 #
elixir
iex(1)> for x <- [1, 2], y <- [3, 4], do: {x, y}
[{1, 3}, {1, 4}, {2, 3}, {2, 4}]
5.3 过滤 #
elixir
iex(1)> for x <- 1..10, x > 5, do: x
[6, 7, 8, 9, 10]
iex(2)> for x <- 1..10, rem(x, 2) == 0, do: x
[2, 4, 6, 8, 10]
5.4 解构 #
elixir
iex(1)> users = [%{name: "Alice", age: 30}, %{name: "Bob", age: 25}]
[%{age: 30, name: "Alice"}, %{age: 25, name: "Bob"}]
iex(2)> for %{name: name} <- users, do: name
["Alice", "Bob"]
5.5 转换结果类型 #
elixir
iex(1)> for x <- 1..5, into: %{}, do: {x, x * 2}
%{1 => 2, 2 => 4, 3 => 6, 4 => 8, 5 => 10}
iex(2)> for x <- 1..5, into: "", do: <<x + 96>>
"abcde"
六、实用示例 #
6.1 数据处理管道 #
elixir
defmodule DataPipeline do
def process(file_path) do
file_path
|> File.stream!()
|> Stream.drop(1)
|> Stream.map(&parse_line/1)
|> Stream.filter(&valid?/1)
|> Enum.reduce(%{}, &aggregate/2)
end
defp parse_line(line) do
line
|> String.trim()
|> String.split(",")
|> List.to_tuple()
end
defp valid?({_date, value}), do: String.to_integer(value) > 0
defp aggregate({_date, value}, acc) do
Map.update(acc, :total, 0, &(&1 + String.to_integer(value)))
end
end
6.2 文本分析 #
elixir
defmodule TextAnalyzer do
def word_frequency(text) do
text
|> String.downcase()
|> String.split(~r/\W+/, trim: true)
|> Enum.reduce(%{}, fn word, acc ->
Map.update(acc, word, 1, &(&1 + 1))
end)
|> Enum.sort_by(fn {_word, count} -> count end, :desc)
|> Enum.take(10)
end
end
七、总结 #
本章学习了:
| 函数 | 用途 |
|---|---|
Enum.map/2 |
映射转换 |
Enum.filter/2 |
过滤元素 |
Enum.reduce/3 |
归约聚合 |
Enum.find/2 |
查找元素 |
Enum.sort/2 |
排序 |
Enum.group_by/2 |
分组 |
Stream |
惰性序列 |
for |
列表推导式 |
|> |
管道操作符 |
准备好学习模块了吗?让我们进入下一章。
最后更新:2026-03-27