ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Learn X in Y Minutes 式 Elixir 快速入门:从 BEAM 基础类型到 Actor 并发(learnxinyminutes-docs)

2026/10/7 9:37:05 拓冰建站 浏览量
Learn X in Y Minutes 式 Elixir 快速入门:从 BEAM 基础类型到 Actor 并发(learnxinyminutes-docs) 文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载导读本文以 learnxinyminutes-docs 仓库中的法语版 Elixir 教程 fr/elixir.md 为核心骨架系统讲解 Elixir 这门构建在 Erlang VMBEAM之上的现代函数式语言从数字、原子、元组、列表、映射等基础类型到模式匹配、控制流、模块与函数、Struct 与异常再到基于 Actor 模型的进程并发与 Agent 状态管理。读完本文你将掌握在iex交互式 Shell 中直接运行并验证每一段 Elixir 代码的能力并理解该语言一切皆表达式、不可变数据、并发原语三大设计支柱的实际用法。文档定位一段可运行的代码即教程learnxinyminutes-docs 是一个以Whirlwind tours旋风式导览为理念的开源项目仓库 README.md 明确将其定位为把编程语言教学直接写成带注释、可直接运行的合法代码边看代码边讲解。Elixir 教程正是这一风格的典型代表——整篇文章的主体是一段可粘贴进iex逐一执行的.ex代码块。该教程在仓库中拥有完整的国际化版本矩阵除法语版 fr/elixir.md 外还有英文原版 elixir.md、zh-cn/elixir.md、zh-tw/elixir.md 以及德、西、意、日、葡、俄、韩等 12 个语言版本各版本内容高度同步便于对照学习。值得注意的仓库规范细节每个文档文件头部都带有一段 YAML frontmattercontributors、translators、filename等字段仓库的 lint/frontmatter.py 会校验 frontmatter 的键名与类型如contributors必须是形如[作者名, 链接]的字符串列表而 lint/encoding.sh 则检查所有 Markdown 文件必须为 UTF-8 / US-ASCII 编码且不带 BOM——这保证了法文重音字符如héllò能正确编码与渲染。环境准备iex与elixirc教程开篇fr/elixir.md即给出两个核心命令行工具# 启动 Elixir 交互式 ShellREPL逐行执行并回显结果 iex # 编译 Elixir 源文件.ex为 Beam 字节码模块 elixirc math.exiexInteractive Elixir用于快速实验表达式、定义模块、查看返回值本文所有代码示例都可在其中直接运行elixirc用于把保存为xxx.ex的模块编译成可被其他模块调用的形式。两者在正确安装 Elixir 后都应位于PATH环境变量中。基础类型从整数到映射数字、原子与元组3 # 整数Integer 0x1F # 整数十六进制字面量即十进制的 31 3.0 # 浮点数Float :hello # 原子Atom以冒号开头值是自身名字的常量字面量 {1, 2, 3} # 元组Tuple内存中连续存储访问开销低 elem({1, 2, 3}, 0) # 1 通过 elem/2 按下标从 0 开始访问元素元组在 BEAM 上以连续内存块存放因此elem/2的随机访问是常量时间与之相对列表则采用链表实现见下文。列表与模式匹配的本质[1, 2, 3] # 列表List实现为链表linked list # 用 [head | tail] 取出头元素与剩余部分 [head | tail] [1, 2, 3] head # 1 tail # [2, 3]这里引入 Elixir继承自 Erlang最重要的语义不是赋值而是模式匹配pattern matching。左侧的[head | tail]是一个模式系统把右侧的值与模式比对成功后把变量绑定到对应位置。若两侧不匹配则抛出错误例如{a, b, c} {1, 2} # ** (MatchError) no match of right hand side value: {1,2}元组长度不同模式匹配失败。二进制、字符串与字符列表1, 2, 3 # 二进制binary字节序列 hello # 字符串string hello # 字符列表char list # 多行字符串三个双引号包裹保留换行 Je suis une chaine de caractères sur plusieurs lignes. # Je suis une chaine de caractères\nsur plusieurs lignes.\n # 字符串一律 UTF-8 编码 héllò # héllò # 字符串本质是二进制字符列表本质是列表 ?a, ?b, ?c # abc [?a, ?b, ?c] # abc # ?a 返回字母 a 的 ASCII 码整数 ?a # 97拼接操作符是二分的列表用二进制/字符串用[1, 2, 3] [4, 5] # [1, 2, 3, 4, 5] hello world # hello world 1, 2, 3 4, 5 # 1, 2, 3, 4, 5 hello world # hello world区间与映射# 区间début..fin两端都包含 1..10 # 1..10 bas..haut 1..10 # 区间同样支持模式匹配解构 [bas, haut] # [1, 10] # 映射Map键值对集合 genders %{david male, gillian female} genders[david] # male # 原子键映射可用点语法访问 genders %{david: male, gillian: female} genders.gillian # female%{key: value}语法是%{:key value}的语法糖点语法map.key则等价于map[:key]两种风格在 Elixir 代码中都很常见函数选项、Struct 字段访问均依赖后者。操作符算术、布尔与严格比较算术与整数除法1 1 # 2 10 - 5 # 5 5 * 2 # 10 10 / 2 # 5.0 注意/ 永远返回浮点数 div(10, 2) # 5 整数除法用 div/2 rem(10, 3) # 1 取余用 rem/2两套布尔逻辑# and / or / not严格要求第一个参数是布尔值 true and true # true false or true # true # 1 and true # ** (BadBooleanError) expected a booléens on left-side of and, got: 1 # / || / !接受任意类型除 false 与 nil 外一切值都视为真 1 || true # 1 返回第一个真值操作数本身 false 1 # false nil 20 # nil !true # false两套操作符的分工很清晰需要强类型布尔断言时用and/or/not做通用真值判断如config[:debug] IO.puts(...)时用/||/!。比较与类型总序1 1 # true 1 ! 1 # false 1 2 # true # / ! 区分整数与浮点 1 1.0 # true 1 1.0 # false # 跨类型比较是允许的 1 :hello # trueElixir 对所有数据类型定义了全序关系number atom reference functions port pid tuple list bit string即数字 原子 引用 函数 端口 进程标识 元组 列表 位串。这意味着可以安全地对异构数据排序或比较。正如 Erlang 之父 Joe Armstrong 所言具体顺序并不重要重要的是存在一个定义良好的全序。fr 版保留了这句引语elixir.md 英文原版则补充了这让我们可以构建混合类型集合如[string, 123, :atom]这一应用场景。控制流if、case、cond 与 try/catchif与caseif false do Cela ne sera pas vu else Cela le sera endElixir 中if是返回值的表达式而非语句。多数控制结构建立在模式匹配之上case把一个值与多个模式逐一比对case {:one, :two} do {:four, :five} - Ne match pas {:one, x} - Match et lie x à :two dans ce cas _ - Match toutes les valeurs end子句从上到下尝试第一个匹配者生效模式中可用变量捕获值可用_通配任意值。下划线惯例不关心的绑定统一用_或_tail命名既表达忽略也避免编译器告警[head | _] [1, 2, 3] head # 1 [head | _tail] [:a, :b, :c] head # :acond多条件分支cond do 1 1 3 - Je ne serai pas vu 2 * 5 12 - Moi non plus 1 2 3 - Mais moi oui endcond依次求值各条件命中第一个为真的分支惯例是把最后一条条件写成true充当else兜底cond do 1 1 3 - Je ne serai pas vu 2 * 5 12 - Moi non plus true - Mais moi oui (représente un else) end官方建议用cond替代多层嵌套if代码更扁平可读。try/catch/after捕获抛出值try do throw(:hello) catch message - Message : #{message}. after IO.puts(Je suis la clause after (après).) end # Je suis la clause after (après). # Message : :hellothrow抛出的是普通值这里是被捕获的原子:hellocatch子句捕获它并可通过#{}插值after子句无论是否捕获都会执行常用于清理资源。注意Elixir 中异常处理的主流是后文的raise/rescuethrow/catch更偏向控制流的非局部跳转。模块与函数def、defp、guard 与管道匿名函数square fn(x) - x * x end square.(5) # 25调用匿名函数须用点号square.(5)以与命名函数square(5)区分。匿名函数同样支持多子句与 guard守卫f fn x, y when x 0 - x y # 当 x 0 时求和 x, y - x * y # 其余情况求积 end f.(1, 3) # 4 f.(-1, 3) # -3when关键字声明 guard对模式匹配做进一步约束如类型检查、范围判断。命名函数与模块defmodule Math do def sum(a, b) do a b end def square(x) do x * x end end Math.sum(1, 2) # 3 Math.square(3) # 9模块用defmodule定义函数用def定义并必须通过模块名调用。将该模块保存为math.ex后在终端执行elixirc math.ex即可编译。公有/私有函数def定义公有函数可被其他模块调用defp定义私有函数仅模块内部可见defmodule PrivateMath do def sum(a, b) do do_sum(a, b) # 内部调用私有函数 end defp do_sum(a, b) do a b end end PrivateMath.sum(1, 2) # 3 # PrivateMath.do_sum(1, 2) # ** (UndefinedFunctionError) 模块外不可见同名多子句 guard多个同名def构成函数子句调用时按定义顺序匹配第一个参数满足子句模式的函数被调用defmodule Geometry do def area({:rectangle, w, h}) do w * h end def area({:circle, r}) when is_number(r) do 3.14 * r * r end end Geometry.area({:rectangle, 2, 3}) # 6 Geometry.area({:circle, 3}) # 28.25999999999999801048 # Geometry.area({:circle, not_a_number}) # ** (FunctionClauseError) no function clause matching in Geometry.area/1这里把按标签区分数据结构:rectangle/:circle与守卫is_number(r)结合当传入非数字半径时两个子句都无法匹配抛出FunctionClauseError——这正是多子句 guard 的典型防御性写法。递归与模块属性由于数据不可变、无传统循环赋值递归是 Elixir 的核心编程方式defmodule Recursion do def sum_list([head | tail], acc) do sum_list(tail, acc head) # 尾递归累加器模式 end def sum_list([], acc) do acc # 空列表终止条件返回累加结果 end end Recursion.sum_list([1, 2, 3], 0) # 6模块属性Module Attributes既有内置属性如moduledoc文档也支持自定义属性在编译期求值defmodule MyMod do moduledoc This is a built-in attribute on a example module. my_data 100 # Attribut personnel自定义属性 IO.inspect(my_data) # 100 end属性在模块编译期生效常用于配置常量、注册文档甚至结合before_compile等钩子做元编程。管道操作符||把左侧表达式的输出作为第一个参数传入右侧函数使数据流自顶向下可读Range.new(1, 10) | Enum.map(fn x - x * x end) | Enum.filter(fn x - rem(x, 2) 0 end) # [4, 16, 36, 64, 100]等价于嵌套写法Enum.filter(Enum.map(Range.new(1,10), fn x - x * x end), fn x - rem(x, 2) 0 end)。管道让生成 1..10 → 平方 → 筛出偶数的流水线一目了然是 Elixir 代码中最具辨识度的惯用法。Struct 与异常类型化的 Map 与 rescueStruct带默认值与编译期保证的 Mapdefmodule Person do defstruct name: nil, age: 0, height: 0 end jean_info %Person{ name: Jean, age: 30, height: 180 } # %Person{age: 30, height: 180, name: Jean} jean_info.name # Jean 点语法访问字段 older_jean_info %{ jean_info | age: 31 } # %Person{age: 31, height: 180, name: Jean} 更新语法产生新 Structdefstruct声明的 Struct 是 Map 的扩展字段未提供时取默认值如age: 0编译期校验字段合法性杜绝拼写错误配合协议Protocol可实现多态。更新操作符%{struct | field: value}保持不可变性——返回新结构原结构不变。raise与rescuetry do raise some error # raise 抛出 RuntimeError rescue RuntimeError - rescued a runtime error _error - this will rescue any error end # rescued a runtime errorraise message默认抛出RuntimeErrorrescue按异常类型匹配子句_error捕获一切异常兜底。每个异常都携带message字段可用in [Type]语法绑定异常变量读取try do raise some error rescue x in [RuntimeError] - x.message end # some error并发Actor 模型的三大原语Elixir 并发基于Actor 模型只需三个原语即可编写并发程序spawn创建进程、send发送消息、receive接收消息。BEAM 上的进程是轻量级调度单元非操作系统线程成百上千个进程可同时运行。spawn 与 PIDf fn - 2 * 2 end # #Functionerl_eval.20.80484245 spawn(f) # #PID0.40.0spawn/1接收一个函数在新进程中异步执行它返回进程标识符PID。send 与 receive消息循环send/2用 PID 向进程发消息receive do阻塞等待并处理消息。一个receive块只处理一条消息要持续处理多条消息函数必须递归调用自己重新进入receive——形成消息循环message loopdefmodule Geometry do def area_loop do receive do {:rectangle, w, h} - IO.puts(Area #{w * h}) area_loop() # 递归回到 receive处理下一条消息 {:circle, r} - IO.puts(Area #{3.14 * r * r}) area_loop() end end end # 编译模块并创建执行 area_loop 的进程 pid spawn(fn - Geometry.area_loop() end) # #PID0.40.0 # 另一种 spawn 形式spawn(Geometry, :area_loop, [])模块、函数名、参数列表 # 向 pid 发送与 receive 模式匹配的消息 send pid, {:rectangle, 2, 3} # Area 6 # {:rectangle, 2, 3} send pid, {:circle, 2} # Area 12.56000000000000049738 # {:circle, 2}receive内部同样使用模式匹配消息{:rectangle, 2, 3}命中第一个子句并解构出w2, h3处理完递归回到监听状态形成无锁的并发服务端模式——这正是 OTPGenServer的雏形。注意send是异步的send pid, msg表达式本身返回消息故上面回显{:rectangle,2,3}。当前进程 PIDiexShell 本身也是一个进程self()返回当前进程的 PIDself() # #PID0.27.0Agent封装可变状态的轻量进程Agent 是持续追踪某个可变值的进程封装适合共享状态场景# Agent.start_link 传入初始状态函数其返回值即 Agent 的初始状态 {ok, my_agent} Agent.start_link(fn - [red, green] end) # Agent.get 传入读取函数函数的返回值即最终取回的结果 Agent.get(my_agent, fn colors - colors end) # [red, green] # Agent.update 用更新函数改写状态 Agent.update(my_agent, fn colors - [blue | colors] end)start_link/2返回{:ok, agent}agent 即 PIDget/3与update/2都接收一个fn该fn以当前状态为参数get的返回值就是你拿到的值update的返回值成为新状态。上述序列执行后Agent 内部状态变为[blue, red, green]。Agent 底层就是进程 消息循环 状态递归的封装在 OTP 应用中常被GenServer取代但对轻量状态管理仍是直观的入门模型。在仓库中继续深入对照英文原版 elixir.md它额外包含跨类型比较构建混合集合、更完整的注释说明是内容最全的基准版本对照中文版 zh-cn/elixir.md、zh-tw/elixir.md 或德语 de/elixir.md、西班牙语 es/elixir.md、日语 ja/elixir.md 等其余 10 个语言版本可交叉验证术语翻译与示例细节学习同族的 Erlang 教程 fr/erlang.md 与 erlang.md理解 Elixir 兼容 Erlang 的底层语言根基了解仓库文档规范CONTRIBUTING.md 说明贡献格式lint/frontmatter.py 定义 frontmatter 校验规则lint/encoding.sh 保证 UTF-8 编码一致性。小结fr/elixir.md 以一段自包含的可运行代码覆盖了 Elixir 的全部核心面不可变数据与模式匹配、case、多子句函数、表达式化控制流if/cond/try、模块化组织def/defp/guard/递归/管道、Struct 与异常defstruct/raise/rescue以及Actor 并发三原语spawn/send/receive与Agent 状态管理。把本文代码逐段粘进iex运行即可在数分钟内建立对这门 BEAM 函数式语言的完整心智模型若想深入生产级并发与容错下一步自然是 OTP 与GenServer——而那已是 Elixir 进阶之旅的下一站。赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐Learn X in Y MinutesSQL 快速入门实战指南learnxinyminutes-docs 德文版解析Learn X in Y MinutesSQL 快速入门实战指南learnxinyminutes docs 德文版解析 结构化查询语言Structure文档教程learnxinyminutes-docs 德文版 Elixir 指南从基础类型到 Actor 并发的完整实战教程learnxinyminutes docs 德文版 Elixir 指南从基础类型到 Actor 并发的完整实战教程 本篇技术指南以本仓库 de/elixir.文档教程Learn X in Y minutesScala 可扩展语言快速入门实战指南基于 learnxinyminutes-docs 深度解读Learn X in Y minutesScala 可扩展语言快速入门实战指南基于 learnxinyminutes docs 深度解读 本文以 lear文档教程上一篇dill源码探索session模块如何实现会话保存和恢复功能下一篇30亿参数撬动千亿市场ERNIE 4.5-VL重构多模态AI产业格局创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考