ElixirSchool 项目教程:深入理解 Elixir 函数机制
elixirschool The content behind Elixir School 项目地址: https://gitcode.com/gh_mirrors/el/elixirschool
前言
在函数式编程语言 Elixir 中,函数是一等公民,这意味着它们可以像其他数据类型一样被传递和操作。本文将全面解析 Elixir 中函数的各种特性和使用方式,帮助开发者掌握这一核心概念。
匿名函数基础
匿名函数是 Elixir 中最基础也是最重要的函数形式,它们没有名称但功能强大。
基本定义
使用 fn
和 end
关键字定义匿名函数:
sum = fn (a, b) -> a + b end
sum.(2, 3) # 返回 5
注意调用匿名函数时需要使用 .
运算符。
简写形式
Elixir 提供了更简洁的匿名函数定义方式:
sum = &(&1 + &2)
sum.(2, 3) # 返回 5
在这种简写形式中:
&1
表示第一个参数&2
表示第二个参数- 以此类推
模式匹配与函数
Elixir 的模式匹配特性同样适用于函数定义,这使得函数可以根据输入参数的不同形式执行不同的逻辑。
多子句函数
handle_result = fn
{:ok, result} -> "处理结果..."
{:ok, _} -> "这行不会执行"
{:error} -> "发生错误!"
end
handle_result.({:ok, 1}) # 返回 "处理结果..."
handle_result.({:error}) # 返回 "发生错误!"
Elixir 会从上到下依次匹配,直到找到第一个匹配的子句。
命名函数详解
命名函数是模块化的基础,它们定义在模块内部,可以被其他模块调用。
基本定义
defmodule Greeter do
def hello(name) do
"Hello, " <> name
end
end
Greeter.hello("Sean") # 返回 "Hello, Sean"
单行简写
对于简单的函数体,可以使用 do:
简写:
defmodule Greeter do
def hello(name), do: "Hello, " <> name
end
递归示例
命名函数非常适合实现递归算法:
defmodule Length do
def of([]), do: 0
def of([_ | tail]), do: 1 + of(tail)
end
Length.of([1, 2, 3]) # 返回 3
函数名称与元数
在 Elixir 中,函数由其名称和参数数量(元数)共同标识:
defmodule Greeter2 do
def hello(), do: "Hello, anonymous!" # hello/0
def hello(name), do: "Hello, " <> name # hello/1
def hello(name1, name2), do: "Hello, #{name1} and #{name2}" # hello/2
end
这些函数虽然同名但元数不同,在 Elixir 中被视为完全不同的函数。
高级模式匹配技巧
映射参数匹配
defmodule Greeter1 do
def hello(%{name: person_name}) do
"Hello, " <> person_name
end
end
fred = %{name: "Fred", age: 95}
Greeter1.hello(fred) # 返回 "Hello, Fred"
保留完整映射
如果需要同时访问特定键和整个映射:
defmodule Greeter2 do
def hello(%{name: person_name} = person) do
IO.puts "Hello, " <> person_name
IO.inspect person
end
end
这种写法会同时绑定 person_name
和 person
两个变量。
私有函数
使用 defp
定义模块内部使用的私有函数:
defmodule Greeter do
def hello(name), do: phrase() <> name
defp phrase, do: "Hello, "
end
守卫子句
守卫子句可以基于参数条件选择不同的函数实现:
defmodule Greeter do
def hello(names) when is_list(names) do
Enum.join(names, ", ") |> hello()
end
def hello(name) when is_binary(name) do
"Hello, " <> name
end
end
默认参数处理
基本用法
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
多子句函数的默认参数
当多个函数子句需要默认参数时,应该这样处理:
defmodule Greeter do
def hello(names, language_code \\ "en")
def hello(names, language_code) when is_list(names) do
Enum.join(names, ", ") |> hello(language_code)
end
def hello(name, language_code) when is_binary(name) do
phrase(language_code) <> name
end
end
总结
Elixir 的函数系统既强大又灵活,通过本文我们学习了:
- 匿名函数的定义和使用
- 命名函数的模块化组织
- 模式匹配在函数中的应用
- 守卫子句的条件判断
- 默认参数的合理使用
掌握这些概念是成为 Elixir 开发者的关键一步,建议读者通过实际编码练习来巩固这些知识。
elixirschool The content behind Elixir School 项目地址: https://gitcode.com/gh_mirrors/el/elixirschool
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考