Elixir命名函数 #
一、函数定义 #
1.1 基本语法 #
命名函数必须在模块内定义:
elixir
defmodule Math do
def add(a, b) do
a + b
end
def subtract(a, b) do
a - b
end
end
1.2 调用函数 #
elixir
iex(1)> Math.add(1, 2)
3
iex(2)> Math.subtract(5, 3)
2
1.3 单行语法 #
elixir
defmodule Math do
def add(a, b), do: a + b
def subtract(a, b), do: a - b
def multiply(a, b), do: a * b
end
1.4 函数体 #
elixir
defmodule Calculator do
def calculate(a, b, operation) do
result = operation.(a, b)
IO.puts("Result: #{result}")
result
end
end
二、多子句函数 #
2.1 基本模式匹配 #
elixir
defmodule ListUtils do
def first([head | _]), do: head
def first([]), do: nil
def last([x]), do: x
def last([_ | tail]), do: last(tail)
def last([]), do: nil
end
2.2 带守卫的子句 #
elixir
defmodule Math do
def abs(x) when x < 0, do: -x
def abs(x), do: x
def sign(x) when x > 0, do: 1
def sign(x) when x < 0, do: -1
def sign(0), do: 0
def factorial(0), do: 1
def factorial(n) when n > 0, do: n * factorial(n - 1)
end
2.3 元组模式匹配 #
elixir
defmodule Result do
def handle({:ok, result}), do: result
def handle({:error, reason}), do: {:error, reason}
def process({:ok, data}) do
{:ok, transform(data)}
end
def process({:error, reason}) do
{:error, reason}
end
defp transform(data), do: String.upcase(data)
end
2.4 映射模式匹配 #
elixir
defmodule User do
def greet(%{name: name, role: :admin}), do: "Hello, Admin #{name}!"
def greet(%{name: name, role: :user}), do: "Hello, #{name}!"
def greet(%{name: name}), do: "Hi, #{name}!"
def greet(_), do: "Hello, stranger!"
end
2.5 子句顺序 #
子句按顺序匹配,更具体的子句应放在前面:
elixir
defmodule Example do
def process(%{type: :special, value: value}), do: "Special: #{value}"
def process(%{type: :normal, value: value}), do: "Normal: #{value}"
def process(%{value: value}), do: "Generic: #{value}"
def process(_), do: "Unknown"
end
三、默认参数 #
3.1 基本语法 #
elixir
defmodule Greeter do
def greet(name, greeting \\ "Hello") do
"#{greeting}, #{name}!"
end
end
Greeter.greet("Alice")
Greeter.greet("Alice", "Hi")
3.2 多个默认参数 #
elixir
defmodule Config do
def build(host \\ "localhost", port \\ 8080, ssl \\ false) do
%{host: host, port: port, ssl: ssl}
end
end
Config.build()
Config.build("example.com")
Config.build("example.com", 443)
Config.build("example.com", 443, true)
3.3 默认参数与守卫 #
elixir
defmodule Math do
def power(base, exponent \\ 2)
def power(base, exponent) when exponent > 0 do
:math.pow(base, exponent)
end
def power(base, 0), do: 1
end
3.4 默认参数与模式匹配 #
当使用默认参数和多子句时,需要函数头声明:
elixir
defmodule Example do
def func(arg1, arg2 \\ "default")
def func(arg1, arg2) when is_binary(arg1) do
"#{arg1}: #{arg2}"
end
def func(arg1, arg2) when is_integer(arg1) do
"#{arg1}: #{arg2}"
end
end
四、私有函数 #
4.1 defp #
使用 defp 定义私有函数:
elixir
defmodule Calculator do
def calculate(a, b, operation) do
result = do_calculate(a, b, operation)
format_result(result)
end
defp do_calculate(a, b, :add), do: a + b
defp do_calculate(a, b, :subtract), do: a - b
defp do_calculate(a, b, :multiply), do: a * b
defp do_calculate(a, b, :divide), do: a / b
defp format_result(result) when is_float(result) do
Float.round(result, 2)
end
defp format_result(result), do: result
end
4.2 公共接口与私有实现 #
elixir
defmodule UserStore do
def create(attrs) do
with {:ok, validated} <- validate(attrs),
{:ok, user} <- persist(validated) do
{:ok, user}
end
end
def find(id) do
case fetch(id) do
{:ok, user} -> {:ok, format(user)}
:error -> {:error, :not_found}
end
end
defp validate(attrs) do
if attrs[:name] && attrs[:email] do
{:ok, attrs}
else
{:error, :invalid_attributes}
end
end
defp persist(attrs) do
{:ok, Map.put(attrs, :id, generate_id())}
end
defp fetch(id) do
{:ok, %{id: id, name: "User #{id}"}}
end
defp format(user) do
Map.put(user, :formatted_name, String.upcase(user[:name]))
end
defp generate_id do
:rand.uniform(1000)
end
end
五、函数文档 #
5.1 @doc #
elixir
defmodule Math do
@doc """
Adds two numbers together.
## Parameters
- `a` - The first number
- `b` - The second number
## Examples
iex> Math.add(1, 2)
3
iex> Math.add(1.5, 2.5)
4.0
"""
def add(a, b), do: a + b
end
5.2 查看文档 #
elixir
iex(1)> h(Math.add)
5.3 @spec #
elixir
defmodule Math do
@spec add(number(), number()) :: number()
def add(a, b), do: a + b
@spec divide(number(), number()) :: {:ok, number()} | {:error, :division_by_zero}
def divide(_, 0), do: {:error, :division_by_zero}
def divide(a, b), do: {:ok, a / b}
end
六、函数类型规范 #
6.1 基本类型 #
elixir
@spec id(any()) :: any()
def id(x), do: x
@spec length(list()) :: non_neg_integer()
def length(list), do: :erlang.length(list)
@spec concat(binary(), binary()) :: binary()
def concat(a, b), do: a <> b
6.2 自定义类型 #
elixir
defmodule User do
@type t :: %__MODULE__{
id: integer(),
name: String.t(),
email: String.t()
}
defstruct [:id, :name, :email]
@spec new(String.t(), String.t()) :: t()
def new(name, email) do
%__MODULE__{id: generate_id(), name: name, email: email}
end
defp generate_id, do: :rand.uniform(1000)
end
七、函数捕获 #
7.1 捕获命名函数 #
elixir
iex(1)> add = &Math.add/2
&Math.add/2
iex(2)> add.(1, 2)
3
iex(3)> Enum.map([1, 2, 3], &Math.add(&1, 1))
[2, 3, 4]
7.2 在模块内捕获 #
elixir
defmodule Example do
def double(x), do: x * 2
def process_list(list) do
Enum.map(list, &double/1)
end
end
八、函数可见性 #
8.1 公共函数 #
elixir
defmodule Public do
def public_function do
"This is public"
end
end
8.2 私有函数 #
elixir
defmodule Private do
def public_function do
private_helper()
end
defp private_helper do
"This is private"
end
end
8.3 函数委托 #
elixir
defmodule Wrapper do
defdelegate upcase(string), to: String
defdelegate reverse(string), to: String
end
Wrapper.upcase("hello")
Wrapper.reverse("hello")
九、最佳实践 #
9.1 函数命名 #
elixir
defmodule Naming do
def valid?(data), do: data != nil
def parse!(string) do
case Integer.parse(string) do
{number, ""} -> number
_ -> raise "Invalid integer"
end
end
def parse(string) do
case Integer.parse(string) do
{number, ""} -> {:ok, number}
_ -> {:error, :invalid_integer}
end
end
end
9.2 函数组织 #
elixir
defmodule WellOrganized do
defstruct [:id, :name]
@type t :: %__MODULE__{id: integer(), name: String.t()}
@doc "Public API"
def create(attrs), do: do_create(attrs)
def find(id), do: do_find(id)
def update(struct, attrs), do: do_update(struct, attrs)
def delete(id), do: do_delete(id)
defp do_create(attrs), do: {:ok, struct(__MODULE__, attrs)}
defp do_find(_id), do: {:ok, %__MODULE__{}}
defp do_update(struct, attrs), do: {:ok, struct(struct, attrs)}
defp do_delete(_id), do: :ok
end
十、总结 #
本章学习了:
| 特性 | 示例 |
|---|---|
| 定义 | def func(arg), do: result |
| 私有函数 | defp func(arg), do: result |
| 多子句 | def handle({:ok, x}), do: x |
| 守卫 | def abs(x) when x < 0, do: -x |
| 默认参数 | def greet(name, msg \\ "Hello") |
| 文档 | @doc "Description" |
| 类型规范 | @spec add(number, number) :: number |
准备好学习递归了吗?让我们进入下一章。
最后更新:2026-03-27