Elixir 编程学习笔记

1. 变量与常量

Elixir 中的变量一旦绑定值即不可改变(immutable),变量通过模式匹配重新绑定。

name = "Alice"
age = 30

注意事项:重新绑定变量不会改变之前的值,仅创建新绑定。

2. 数据类型

Elixir 支持多种数据类型,包括整数、浮点数、布尔值、字符串、列表和元组。

height = 1.75
is_student = true
names = ["Alice", "Bob"]
pair = {"Alice", 25}

易错点:字符串用双引号,元组和列表中的数据不可变。

3. 条件控制

Elixir 中的条件控制语句有 ifunlesscase

if age > 18 do
    "Adult"
else
    "Minor"
end

注意事项:case 可用于复杂条件,匹配分支必须涵盖所有情况。

4. 函数

函数定义使用 def,匿名函数使用 fn

defmodule Greeter do
  def greet(name), do: "Hello, " <> name
end

greet = fn name -> "Hello, " <> name end

易错点:函数体中若有多行代码,需用 do ... end 包裹。

5. 模式匹配

Elixir 中的模式匹配通过 = 进行赋值和匹配。

{:ok, result} = {:ok, 42}

注意事项:模式匹配失败会引发错误,确保左侧模式与右侧值一致。

6. 递归

Elixir 中递归用于替代循环。

defmodule Math do
  def sum(0), do: 0
  def sum(n), do: n + sum(n - 1)
end

易错点:确保递归函数有终止条件,否则会导致栈溢出。

7. 管道操作符

管道操作符 |> 将左侧的结果传入右侧函数,简化函数链调用。

"elixir" |> String.upcase() |> String.reverse()

注意事项:确保管道操作的每个步骤返回值与下一个函数的参数类型匹配。

8. 并发编程

Elixir 支持并发编程,spawn 启动新进程。

spawn(fn -> IO.puts("Hello from another process!") end)

注意事项:Elixir 中的进程非常轻量,不要滥用全局状态。

9. 宏

Elixir 支持宏,用于生成代码。

defmodule MyMacro do
  defmacro say_hello(name) do
    quote do
      IO.puts("Hello, " <> unquote(name))
    end
  end
end

注意事项:宏生成代码时,需使用 quoteunquote

高级与小众用法

组合函数

Elixir 支持将函数作为参数传递和返回,用于函数组合。

compose = fn f, g -> fn x -> f.(g.(x)) end end

注意事项:确保组合函数的参数和返回类型匹配。

守卫条件

使用守卫条件定义有条件的模式匹配。

def check(x) when x > 0, do: "Positive"
def check(x) when x < 0, do: "Negative"

易错点:守卫条件使用 when 定义,必须为布尔表达式。

Enum 和 Stream

Elixir 提供 EnumStream 模块进行集合操作。

Enum.map([1, 2, 3], &(&1 * 2))  # 即时计算
Stream.map([1, 2, 3], &(&1 * 2)) |> Enum.to_list()  # 惰性计算

注意事项:Stream 实现惰性求值,提高大数据处理效率。

进程间通信

Elixir 进程通过 sendreceive 进行消息传递。

send(self(), {:msg, "Hello"})
receive
  {:msg, text} -> IO.puts(text)
end

注意事项:使用 receive 匹配消息,未匹配的消息将被忽略。

匿名函数捕获

Elixir 支持使用 &&1 简化匿名函数。

Enum.map([1, 2, 3], &(&1 * 2))

易错点:捕获表达式需明确参数位置,避免不清晰代码。

自定义异常

Elixir 允许定义自定义异常类型。

defmodule MyError do
  defexception message: "Default error message"
end

注意事项:自定义异常需定义 message 字段,方便错误信息传递。