You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elixir元编程编译流程疑问:代码输出顺序为何是BBB hh in BBB AAA

嘿,这个问题刚好戳中Elixir编译和执行时机的关键点,我来给你掰扯清楚为什么输出顺序是BBB → hh in BBB → AAA~

先把你的代码贴出来方便对照:

defmodule BBB do
  IO.puts "BBB"
  defmacro hh do
    IO.puts "hh in BBB"
  end
end
defmodule AAA do
  IO.puts "AAA"
  require BBB
  BBB.hh
end

核心原因:Elixir的「编译时操作」和「运行时操作」是分开的

Elixir处理模块代码时,会把编译时要做的事和运行时才做的事拆成两个阶段执行,这就是你看到顺序“反常”的关键。

第一步:处理BBB模块

当解释器/编译器遇到defmodule BBB时,会直接按顺序执行模块内的顶层代码(不在def/defmacro里的代码):

  • 首先执行IO.puts "BBB",所以第一个输出是BBB。
  • 然后定义宏hh——这只是把宏的代码存起来,宏内部的IO.puts "hh in BBB"此时不会执行,因为宏是编译时调用的,只有当它被调用时才会触发执行。

第二步:处理AAA模块

处理defmodule AAA时,Elixir会优先处理所有编译时指令,再执行运行时的顶层代码:

  1. 先处理编译时操作:
    • 看到require BBB:这是编译时指令,确保BBB模块已经被编译(这里已经完成了)。
    • 看到BBB.hh:因为hh是用defmacro定义的宏,所以这是一个编译时调用——此时会立即执行宏内部的代码IO.puts "hh in BBB",输出第二个内容hh in BBB。
  2. 再执行运行时顶层代码:
    所有编译时操作完成后,才会执行模块里的IO.puts "AAA",输出第三个内容AAA。

这样整个顺序就完全对应上你看到的输出啦!

内容的提问来源于stack exchange,提问作者chenyuandong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:14:10