资讯详情

资讯详情

Learn X in Y Minutes 仓库解读:Elixir 快速入门指南全解析——从基础类型到并发与 Agent 的实战教程

文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载Elixir 是一门构建在 Erlang VMBEAM之上的现代函数式编程语言本仓库 ro/elixir.md 以代码即文档的形式用罗马尼亚语完整演示了 Elixir 的核心语法与并发模型。本文以该文档为骨架逐节拆解其涵盖的基本类型、操作符、控制流、模块与函数、结构体与异常、进程并发及 Agent 状态管理并结合仓库中英文原版 elixir.md、zh-cn/elixir.md 及 CONTRIBUTING.md 的风格约定帮助读者快速掌握可直接复制运行的 Elixir 代码片段理解这门语言与 Erlang 生态的深层关系。文档定位Learn X in Y Minutes 项目的可运行教程范式本仓库是 Learn X in Y Minutes 项目的文档库README.md 将其宗旨概括为以有效、带注释的代码形式呈现热门编程语言的旋风式导览——即用一段可执行的代码而非长篇论述来讲解一门语言。这一范式在 Elixir 教程中体现得淋漓尽致全文主体是一个完整的elixir代码块每一行都是经过验证的合法 Elixir 表达式注释即讲解代码块顶部直接给出环境前提用iex命令进入 Elixir 交互式 Shell用elixirc命令编译模块二者需正确安装 Elixir 后位于 PATH 中CONTRIBUTING.md 的风格指南要求代码示例优先于文字说明尽量少用文字这正是该文档注释即教程的写作依据仓库 lint/frontmatter.py 会对每篇文档的 YAML 头contributors、translators、filename 等字段做格式校验lint/encoding.sh 则确保所有 Markdown 文件保持 UTF-8 无 BOM 编码——这些质量保障机制保证了教程代码的可信度。本教程由四位贡献者撰写英文版并由 Vitalie Lazu 翻译为罗马尼亚语与英文原版 elixir.md 内容一一对应是理解 Elixir 的完整入门素材。基础类型从原子到位串的数据全景教程首先用一组最小表达式勾勒出 Elixir 的全部基础类型每种类型都伴随可立即在iex中验证的示例。数字、原子与元组3 # 整型integer 0x1F # 十六进制整型值为 31 3.0 # 浮点型float :salut # 原子atom以冒号开头的常量其值就是自身名字 {1,2,3} # 元组tuple在内存中连续存储 elem({1, 2, 3}, 0) # 1用 elem/2 按下标取元素下标从 0 开始原子是 Elixir 中极具辨识度的类型——它既是布尔值true/false的底层实现也是消息协议、函数标签的常用载体这在后文case模式匹配与并发消息示例中会反复出现。元组因内存连续存放适合固定数量、少量元素的场景如函数返回{:ok, result}或{:error, reason}二元组。列表、模式匹配与二进制[1,2,3] # 列表list底层是链表实现 # 每个非空列表都有头head首元素和尾tail其余元素组成的列表 [cap | coadă] [1,2,3] cap # 1 coadă # [2, 3] 1,2,3 # 二进制binary教程在此处点出 Elixir 最重要的心智模型表示模式匹配pattern matching而非赋值。左侧是模式pattern右侧是值表达式两侧必须结构一致才能匹配成功。列表的[head | tail]解构正是这一语义的直接应用。若两侧不匹配则抛出MatchError{a, b, c} {1, 2} # ** (MatchError) no match of right hand side value: {1,2}字符串、字符列表与 UTF-8 编码salut # Elixir 字符串string salut # Erlang 字符列表char list Sunt un șir de caractere pe mai multe linii. # 多行字符串heredoc Bună dimineața # Bună dimineața字符串一律 UTF-8 编码 ?a, ?b, ?c # abc字符串本质是二进制 [?a, ?b, ?c] # abc字符列表本质是列表 ?a # 97?a 返回字符 a 的 ASCII 码这段代码揭示了 Elixir 的经典坑与美双引号字符串实际上是 UTF-8 编码的二进制bitstring单引号字符列表则是普通列表。教程用?a返回 97 来说明两者的转换关系。相应地拼接操作符也因此分道扬镳——链表用二进制用[1,2,3] [4,5] # [1,2,3,4,5] Salut lume # Salut lume 1,2,3 4,5 # 1,2,3,4,5 Salut lume # Salut lume区间与映射1..10 # 区间range两端均含端点 început..sfîrșit 1..10 # 区间同样支持模式匹配 [început, sfîrșit] # [1, 10] # 映射map键值对容器 genuri %{Ion bărbat, Maria femeie} genuri[Ion] # bărbat # 键为原子的映射有专用语法与点访问 genuri %{ion: bărbat, maria: femeie} genuri.ion # bărbat映射是 Elixir 中用途最广的复合数据结构教程同时展示了通用键和key:原子键两种写法后者可直接用点号访问字段——这正是后文struct结构的语法基础。操作符严格布尔、宽松逻辑与全序比较教程的操作符章节刻意区分了两套逻辑操作符这是新手最容易混淆的地方1 1 # 2 10 / 2 # 5.0除法永远返回浮点数 div(10, 2) # 5整数除法 rem(10, 3) # 1取余 # 严格布尔操作符要求第一个参数必须是布尔值 true and true # true false or true # true # 1 and true # ** (BadBooleanError) expected a boolean on left-side of and, got: 1 # 宽松逻辑操作符接受任意类型除 false 和 nil 外均视为真 1 || true # 1短路返回第一个真值 false 1 # false nil 20 # nil !true # false比较操作符方面教程特别指出/!在整型与浮点型比较时更严格1 1 # true 1 ! 1 # false 1 2 # true 1 1.0 # true宽松相等 1 1.0 # false严格相等类型也须一致 1 :salut # true可跨类型比较最后一点值得展开Elixir 为所有数据类型定义了全局全序——数字 原子 引用 函数 端口 进程 元组 列表 字符串。教程引用 Joe Armstrong 的话说实际顺序并不重要重要的是全序被良好定义。这意味着混合类型集合可以安全排序为构建如[string, 123, :atom]这样的异构集合提供了底层保证。控制流基于模式匹配的分支家族教程指出Elixir 的许多控制结构都依赖于模式匹配随后依次演示if、case、cond与try/catch# if 表达式Elixir 中一切皆表达式if 也有返回值 if false do Aceasta nu veți vedea niciodată else Aceasta veți vedea end # case将值与多个模式依次比对 case {:unu, :doi} do {:patru, :cinci} - Aceasta nu se potrivește {:unu, x} - Aceasta se potrivește și atribuie lui x :doi în acest bloc _ - Aceasta se va potrivi cu orice valoare end模式匹配中的下划线_被称为匿名变量anonymous variable用于占位那些不关心的值[cap | _] [1,2,3] cap # 1 [cap | _coadă] [:a, :b, :c] # 带下划线前缀的命名可提升可读性 cap # :a当分支条件多于两个时教程推荐用cond取代嵌套的if并以true作为兜底分支等价于elsecond do 1 1 3 - Aceasta nu veți vedea niciodată 2 * 5 12 - Pe mine la fel true - Aceasta veți vedea (este else în esență) end异常投掷与捕获使用try/catch其after子句无论是否捕获到值都会执行类似其他语言的finallytry do throw(:salut) catch mesaj - Am primit #{mesaj}. after IO.puts(Sunt în blocul after.) end # Sunt în blocul after. # Am primit salut模块与函数匿名函数、守卫、递归与管道匿名函数与守卫子句匿名函数用fn ... end定义调用时必须带点号f.(args)square fn(x) - x * x end square.(5) # 25 # 支持多子句与守卫guard守卫用 when 关键字引入 f fn x, y when x 0 - x y x, y - x * y end f.(1, 3) # 4 f.(-1, 3) # -3守卫是对模式匹配的精细化约束当x 0时执行加法否则回退到乘法子句。Elixir 还内置了大量可直接调用的函数如is_number/1、is_list/1、elem/2。defmodule、def 与 defp用defmodule将函数分组为模块模块内用def定义公有函数、defp定义私有函数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教程提示把上述代码保存为math.ex后在终端执行elixirc math.ex即可编译elixirc也是本仓库文档约定的编译入口命令。私有函数的可见性边界清晰可见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)函数定义同样支持守卫与多子句调用时按定义顺序取第一个匹配成功的子句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注意守卫失败不会抛出异常而是导致无匹配子句最终抛出FunctionClauseError——这是函数式语言常见的错误形态教程刻意保留了这一边界示例。递归不可变数据下的循环替代由于变量不可变循环在 Elixir 中由递归承担。教程用一个累加器accumulator模式的求和函数演示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两个同名同参arity 均为 2的子句构成经典空列表终止 非空递归结构这在后文的并发receive循环中还会再次出现。模块属性与管道操作符模块属性module attribute既是编译期常量也是元数据载体defmodule MyMod do moduledoc Este un atribut incorporat my_data 100 # Acesta e atributul nostru IO.inspect(my_data) # 100 end管道操作符|是 Elixir 可读性的灵魂——它将左侧表达式的结果作为第一个参数传入右侧函数让数据流自上而下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]这段代码依次生成 1..10 区间、平方映射、过滤偶数最终得到[4, 16, 36, 64, 100]将数据流思想表达得淋漓尽致。结构体与异常处理defstruct在映射之上构建结构体struct带来默认值、编译期字段检查与多态能力defmodule Person do defstruct name: nil, age: 0, height: 0 end joe_info %Person{ name: Joe, age: 30, height: 180 } # %Person{age: 30, height: 180, name: Joe} joe_info.name # Joe点号访问字段 older_joe_info %{ joe_info | age: 31 } # %Person{age: 31, height: 180, name: Joe}更新语法%{ struct | field: value }结构体更新的%{ struct | ... }语法会返回新结构体而保持原值不变完美体现不可变语义。异常处理用try/rescue可按异常类型或通配符分支捕获try do raise o eroare rescue RuntimeError - a fost prinsă o eroare runtime _error - aici vor fi prinse toate erorile end # a fost prinsă o eroare runtime # 所有异常都有 message 字段 try do raise o eroare rescue x in [RuntimeError] - x.message end # o eroare第二种写法用x in [RuntimeError]将异常绑定到变量x从而访问x.message——这也是真实项目中提取错误信息的常用模式。并发Actor 模型三原语教程断言Elixir 的并发基于 Actor 模型只需三个原语即可编写并发程序——创建进程spawn、发送消息send、接收消息receive。这份简洁正是 Erlang VM 二十年电信级并发工程的沉淀。创建进程f fn - 2 * 2 end # #Functionerl_eval.20.80484245 spawn(f) # #PID0.40.0spawn/1接收一个函数并立即返回进程标识符 pidprocess identifier。发送与接收消息defmodule Geometry do def area_loop do receive do {:rectangle, w, h} - IO.puts(Aria #{w * h}) area_loop() # 递归回到 receive处理下一条消息 {:circle, r} - IO.puts(Aria #{3.14 * r * r}) area_loop() end end end pid spawn(fn - Geometry.area_loop() end) # #PID0.40.0 pid spawn(Geometry, :area_loop, []) # 等价写法按模块/函数/参数列表派生 send pid, {:rectangle, 2, 3} # Aria 6 # {:rectangle,2,3} send pid, {:circle, 2} # Aria 12.56000000000000049738 # {:circle,2} self() # #PID0.27.0iex Shell 本身也是一个进程这段示例揭示了receive do的关键纪律一个receive do块每次只处理一条消息要持续处理就必须让函数递归调用自身回到receive。消息本身是任意 Elixir 值此处是带原子标签的元组接收端用模式匹配挑选感兴趣的消息——这与前文case的模式匹配机制一脉相承。self/0则返回当前进程的 pid用于 Shell 与业务进程间的通信。Agent有状态的轻量进程封装并发章节的收尾是 Agent——一个持续跟踪某个可变值的进程抽象是 Elixir 官方Agent模块基于 GenServer 的简化封装{ok, my_agent} Agent.start_link(fn - [roșu, verde] end) # 初始状态 传入函数fn - [roșu, verde] end的返回值 Agent.get(my_agent, fn colors - colors end) # [roșu, verde] # get/2 把当前状态传给回调函数回调的返回值即 get 的返回值 Agent.update(my_agent, fn colors - [albastru | colors] end) # update/2 用回调的返回值替换状态在列表头部插入 albastruAgent 的用法模式清晰start_link/1初始化状态get/2以函数式方式读取状态读不改变状态update/2以函数式方式更新状态。所有操作都是纯函数作用于当前状态天然适配不可变语义是计数器、配置缓存等有状态场景的轻量选择。从实现角度看Agent 背后是 BEAM 上标准的GenServer行为教程借此为读者后续深入 OTP 打下铺垫。延伸学习路径与仓库实践建议原文档在代码块之外附有罗马尼亚语的Link-uri utile有用链接清单包括 Elixir 官方入门指南、官方文档、Dave Thomas 的《Programming Elixir》、Fred Hebert 的《Learn You Some Erlang for Great Good!》以及 Joe Armstrong 的《Programming Erlang》等权威资源。结合本仓库建议的实践路径是逐行运行安装 Elixir 后把 ro/elixir.md 代码块中的表达式逐段粘贴进iex验证输出#后即为预期结果对照多语言版本将罗马尼亚语版本与英文原版 elixir.md、中文版 zh-cn/elixir.md 对照阅读可消除翻译差异带来的歧义例如罗马尼亚语版用spawn(Geometry, :area_loop, [])而中文旧版曾使用-发送符号应以send为准动手编译将Math、Geometry模块存为.ex文件用elixirc编译体验模块即编译单元的工作流深入并发基于Geometry.area_loop扩展多进程收发、进程链接与监督树再过渡到 OTP 的 GenServer。结语一篇文档一门语言的心智模型ro/elixir.md 的价值不在于罗列语法而在于用最少的文字串起 Elixir 的四根主线模式匹配驱动的数据解构、不可变数据与递归、基于 Actor 的轻量进程并发、以及函数式状态管理。它同时示范了 Learn X in Y Minutes 项目代码即文档的创作范式——CONTRIBUTING.md 要求代码示例优先、行宽不超过 80 字符、全文 UTF-8 编码这些约定由 lint/frontmatter.py 与 lint/encoding.sh 自动守护。当你把文中的每一行代码敲进iex并看到相同的输出时你收获的不只是 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 Minutes 式 Elixir 快速入门从 BEAM 基础类型到 Actor 并发learnxinyminutes-docsLearn X in Y Minutes 式 Elixir 快速入门从 BEAM 基础类型到 Actor 并发learnxinyminutes docs文档教程TinyUSB 版本发布全流程指南从版本号提升、changelog 整理到 tag 落地TinyUSB 版本发布全流程指南从版本号提升、changelog 整理到 tag 落地 本篇技术指南围绕 TinyUSB 仓库内置的发布技能 make r文档教程Python 2.7 快速入门Learn X in Y Minutes 仓库 Python 2legacy教程深度解读Python 2.7 快速入门Learn X in Y Minutes 仓库 Python 2legacy教程深度解读 本文以 Learn X in Y文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →