Anki
Anki 背诵卡片 — Elixir 速通
格式说明:每张卡片包含 问题(正面) / 答案(背面) / 标签。 适合在 0001-0005 课程读完一遍后,挑这些纯记忆型概念制成卡片。
一、基础语法 / 数据结构
字面量类型
Q: Elixir 中 atom 是什么?给 3 个例子。
A: 像 Clojure 的 keyword / Haskell 的 Symbol。:ok、:error、:running、:foo_bar。
BEAM 内部用地址比较,极快。是所有”标签 / 枚举”的基础。
Tags: elixir-basics
Q: Elixir 的 String 用什么引号?Charlist 用什么引号?
A: String = 双引号 "hello"(UTF-8 binary)。
Charlist = 单引号 'hello'(Erlang 遗留的整数列表,几乎不用)。
Tags: elixir-basics
Q: Elixir 中 nil 和 false 是什么关系?
A: 都是 atom。nil = :nil,false = :false。
|| 把 nil 和 false 都视为”假”。unless x 等同于 if !x。
Tags: elixir-basics
Q: Keyword List [a: 1, b: 2] 等价于什么?
A: [{:a, 1}, {:b, 2}] — 就是 list of tuples。
用于”命名参数 opts”,Keyword.get(opts, :key, default) 取值。
Tags: elixir-basics
Q: Tuple {:ok, value} 跟 Map %{a: 1} 的性能差异?
A: Tuple 定长 N≤10,读写 O(1),比 Map 还快。用 case 模式匹配。
Map 是 hashmap,O(log n),按 key 随机访问。
Tags: elixir-basics
绑定 / 不可变
Q: x = 10; x = 20 在 Elixir 中是什么意思?
A: 重新绑定到新值 20,不是修改。
Elixir 一切数据不可变,变量是”标签”不是”盒子”。
Tags: elixir-basics
Q: Pin operator ^x 的作用?
A: 在模式匹配中防止重新绑定,沿用外面的 x 值。
case y do; ^x -> ...; _ -> ... end 中 ^x 表示”匹配 x 绑定的那个值”。
Tags: elixir-basics
Q: Elixir 中 = 跟 C/Java = 的根本区别?
A: Elixir = 是模式匹配 + 绑定。
C/Java = 是赋值(修改内存)。
x = {1, 2} 在 Elixir 是”匹配 {1,2} 模式,绑定 x”;C 是”把 1,2 写入 x 内存”。
Tags: elixir-basics
二、模式匹配 / 控制流
Q: case expr do ... end 中 _ 通配符放错位置会怎样?
A: 永远匹配不上后面任何子句。
_ 必须放最后,定义顺序敏感——前定义先匹配。
Tags: elixir-pattern
Q: cond 跟 case 什么时候用?
A: case — 模式匹配(按结构分支)
cond — 布尔条件分支(像 if/elif 链)
if/unless — 单分支
with — 链式 {:ok, x} 解包
Tags: elixir-control
Q: Elixir 的 if 跟 Java 的 if 区别?
A: Elixir if 是表达式有返回值,可以放在 = 右边。
Java if 是语句,Java 14+ if 表达式才类似。
Tags: elixir-control
Q: Elixir 的”let it crash” 哲学实践是?
A: 进程不防御性 try-catch 全部错误。崩了让 Supervisor 重启。
跟 Java “满屏 try-catch” 相反。
Tags: elixir-philosophy
三、并发 / OTP
Q: BEAM 进程的初始内存大小?跟 Java Thread、goroutine 对比? A: BEAM 进程 ~ 0.5 KB;goroutine ~ 2 KB;Java Thread ~ 512 KB。 单机可创建百万级 BEAM 进程。 Tags: elixir-concurrency
Q: BEAM 调度是抢占式还是协作式? A: 抢占式——每 2000 reductions 强制切换。 死循环不会卡死整个 VM(Go 的 goroutine 是协作式)。 Tags: elixir-concurrency
Q: GenServer.call vs GenServer.cast 区别?
A: call 同步等 reply(阻塞);cast 异步不阻塞,立即返回。
call 失败有 timeout;cast 不返回任何错误(fire-and-forget)。
Tags: elixir-concurrency
Q: Supervisor 4 种重启策略?
A: :one_for_one 一个崩了只重启那个(默认)
:one_for_all 一个崩了全部重启
:rest_for_one 一个崩了它和它之后启动的子进程重启
:temporary 不重启
Tags: elixir-otp
Q: BEAM 进程之间通信方式?
A: 唯一方式:消息传递(send(pid, msg))。不允许共享内存。
消息是值复制(小对象)或 COW(large binary)。
Tags: elixir-concurrency
Q: send(dead_pid, msg) 到不存在的 pid 会怎样?
A: 消息丢失,无声无息。BEAM 不报错。
项目里 Oban 用 PG 持久化消息,进程挂了消息不丢。
Tags: elixir-concurrency
四、模块 / 宏 / 行为 / 协议
Q: def vs defp 区别?
A: def 公开函数(外部可调);defp 私有函数(只能本模块内调)。
跟 Java public / private 类似。
Tags: elixir-module
Q: use vs import vs require vs alias 区别?
A: alias — 给模块起别名(alias Pipeline.Repo 之后写 Repo)
import — 导入函数到当前命名空间
require — 让宏可见(宏要先 require 才能用)
use — 调对方模块的 __using__/1 宏,注入代码到当前模块
Tags: elixir-module
Q: use Oban.Worker 内部大致调什么?
A: 调 Oban.Worker.__using__/1 宏,注入 use GenServer + @behaviour Oban.Worker + perform/1 框架代码。
Tags: elixir-macro
Q: Elixir 协议(Protocol)跟 Java interface 的核心区别? A: 协议可以给已有类型(包括第三方)加 dispatch。 Interface 不能给已存在的 class 加方法(除非改源码)。 Elixir 协议在编译期展开成 case 模式匹配,运行时极快。 Tags: elixir-protocol
Q: 行为(@behaviour)写在一个模块里,编译时会做什么?
A: 读对方模块所有 @callback,检查当前模块是否实现全部。
漏实现:编译警告;签名错:编译错误。
Tags: elixir-behaviour
Q: defmacro 跟 def 关键区别?
A: defmacro 在编译期执行,接收和返回 AST;def 在运行期执行普通逻辑。
Elixir 宏跟 Clojure 宏同源于 homoiconicity(代码即数据)。
Tags: elixir-macro
Q: quote do 1 + 2 end 返回什么?
A: AST 三元组 {:+, _, [1, 2]}。这是宏操作代码的基础。
Tags: elixir-macro
Q: Elixir 什么时候用协议 vs 行为? A: 协议 — 已有 N 个类型,想加统一接口(如”如何序列化”)。 行为 — 接口固定,实现可能多个(如依赖注入,运行时切换)。 Tags: elixir-polymorphism
五、Ecto / Oban
Q: Ecto Changeset 是什么?
A: 一个流程描述(不是值):cast(白名单字段)+ validate_required(必填校验)。
Repo.insert!/1 提交 changeset。
Tags: elixir-ecto
Q: Repo.insert! 跟 Repo.insert 区别?
A: ! 结尾的版本失败时抛异常;不带 ! 返回 {:ok, record} 或 {:error, changeset}。
跟 Ruby 的 ! 区别(Ruby ! 表示 in-place 修改)。
Tags: elixir-ecto
Q: on_conflict: :nothing 的作用?
A: PostgreSQL INSERT ... ON CONFLICT DO NOTHING——冲突时忽略。
用于幂等去重(拉消息时按主键)。
Tags: elixir-ecto
Q: Oban Worker 的 perform/1 接收什么?
A: %Oban.Job{} struct(带 args 字段)。
内部就是个 GenServer,Oban 调度时调用 perform/1。
Tags: elixir-oban
六、错误处理
Q: Elixir 错误的两种表示?
A: 1) {:ok, value} / {:error, reason} tagged tuple(预期错误,80% 场景)
2) try/rescue 异常(意外崩溃,20% 场景)
哲学:“errors are values, not exceptions”。
Tags: elixir-error
Q: Elixir 默认参数怎么写?
A: def f(x \\ 0) —— \\ 双反斜杠。
跟 Python def f(x=0) 的 = 不同。
Tags: elixir-syntax
七、与其他语言速记
Q: Elixir 跟 Go 的核心区别? A: Elixir 进程独立堆,消息传递唯一;Go goroutine 共享堆,channel 通信。 Elixir 抢占式调度;Go 协作式调度。 Elixir 支持热代码升级;Go 不支持。 Tags: elixir-vs-go
Q: Elixir 跟 Clojure 最像的?
A: 都支持宏(homoiconic)、都是 FP、都是动态类型。
区别:Elixir 在 BEAM,Clojure 在 JVM。
Clojure 宏完全卫生,Elixir 宏手动卫生(var!)。
Tags: elixir-vs-clojure
Q: BEAM 进程 vs Java Thread vs goroutine 初始内存? A: BEAM 0.5 KB < goroutine 2 KB <<< Java Thread 512 KB。 1000x 差距。BEAM 单机百万进程。 Tags: elixir-runtime
Q: 99.999% 可用性 / 长连接选哪个语言? A: Elixir / Erlang(30 年电信验证)。 WhatsApp / Discord / Ericsson AXD301 都跑在 BEAM。 Tags: elixir-selection
八、ex/elixir 项目特有
Q: ex/elixir 项目里 Pipeline.Application.start/2 的监督树根是什么?
A: Pipeline.Supervisor(one_for_one 策略)。
包含 Pipeline.Repo / Finch / Oban / Bandit。
Tags: ex-elixir
Q: Pipeline.Llm 行为 + 实现的”配置驱动多态”模式靠什么?
A: Application.get_env(:pipeline, :llm, Pipeline.Llm.Real) 读配置。
默认 Real,要切 Dummy:Application.put_env(:pipeline, :llm, Pipeline.Llm.Dummy)。
Tags: ex-elixir
Q: Pipeline.Web 用什么 HTTP 服务器?
A: Bandit({Bandit, plug: Pipeline.Web, port: 8002, ip: {127, 0, 0, 1}})。
绑 127.0.0.1(内部工具,无鉴权)。
Tags: ex-elixir
Q: Pipeline.Dag.graph/0 返回什么?
A: %{nodes: [...], edges: [...]} —— 静态拓扑 + 每节点实时数据流入量。
前端 n8n 风格”网线”视图的数据源。
Tags: ex-elixir
Q: ex/elixir 的 Oban 失败任务怎么处理?
A: POST /api/retry/:id 调 Oban.retry_job/2 重试。
GET /api/failed 列 oban_jobs where state='discarded'。
Tags: ex-elixir
九、必背哲学口诀
Q: “Errors are values, not exceptions” 在 Elixir 中怎么实践?
A: 预期失败返回 {:error, reason},不抛异常。
让调用方用 case / with 处理。
意外崩溃 → 让进程死,让 Supervisor 重启。
Tags: elixir-philosophy
Q: “Don’t write a macro if a function can do it” 含义?
A: 能用函数就别用宏。宏难调试、难读。
宏的正当用途:定义 DSL(schema、test、use)。
Tags: elixir-philosophy
Q: “Code is data” 在 Elixir 怎么体现?
A: quote 把代码转 AST(三元组),unquote 把 AST 嵌回代码。
宏就是操作 AST 的函数。这是 Elixir 元编程的根基。
Tags: elixir-philosophy
CSV 导入格式(Anki 直接导入)
Q;A;Tags
"BEAM 进程初始内存大小?跟 Java Thread、goroutine 对比?";BEAM 进程 ~ 0.5 KB;goroutine ~ 2 KB;Java Thread ~ 512 KB。单机可创建百万级 BEAM 进程。;elixir-concurrency
"BEAM 调度是抢占式还是协作式?";抢占式——每 2000 reductions 强制切换。Go 的 goroutine 是协作式。;elixir-concurrency
"`use` vs `import` vs `require` vs `alias` 区别?";alias=模块别名;import=导入函数;require=让宏可见;use=调对方 __using__/1 宏注入代码;elixir-module
"协议(Protocol)跟 Java interface 的核心区别?";协议可以给已有类型加 dispatch,interface 不能扩展已存在类型;elixir-protocol
"99.999% 可用性选哪个语言?";Elixir / Erlang(30 年电信验证);elixir-selection