gpt4 book ai didi

elixir - 什么时候应该在 .exs 文件中使用 defmodule

转载 作者:行者123 更新时间:2023-12-04 11:02:39 24 4
gpt4 key购买 nike

我尝试创建一个没有 config.exs 的混合项目,所以我创建了该文件。

我引用了一个 phoenix 项目的 config.exs

我看到 config.exs 没有模块定义。我尝试在 .ex 文件中声明一个独立函数,它按预期引发错误

** (ArgumentError) cannot invoke def/2 outside module

然后我假设 .exs 可以不用 defmodule 来写然后我看到 mix.exs 它有模块定义。为什么会这样?

我的问题是为什么要保留 config.exs 没有模块定义,而保留 mix.exs 有定义?

什么时候应该在 .exs 中使用 defmodule,什么时候不应该?

最佳答案

如果您查看 mix.exs 文件,您会注意到:

use Mix.Project

现在这个file包含:

  @doc false
defmacro __using__(_) do
quote do
@after_compile Mix.Project
end
end

# Invoked after each Mix.Project is compiled.
@doc false
def __after_compile__(env, _binary) do
push(env.module, env.file)
end

@after_compile 是在 elixir/kernel.ex 中定义的宏即使它是一种奇怪的形式,它是由 __using__mix.exs 调用的。由于您不能在模块外调用宏,因此您需要在 mix.exs 文件中包含一个模块。

为了更清楚地说明这一点,让我们尝试删除 mix.exs 中的模块并运行项目:

* (ArgumentError) cannot invoke @/1 outside module
(elixir) lib/kernel.ex:5230: Kernel.assert_module_scope/3
(elixir) expanding macro: Kernel.@/1
mix.exs:2: (file)
(mix) expanding macro: Mix.Project.__using__/1
mix.exs:2: (file)
(elixir) expanding macro: Kernel.use/1
mix.exs:2: (file)

所以你的问题的答案是,钩子(Hook) @after_compile 不能在没有模块的情况下被调用,因为钩子(Hook)本身就是宏。该钩子(Hook)很可能用于在所有文件编译完成后自动加载项目。

PS: push/3 函数调用了一个有趣的模块函数:

Mix.ProjectStack.push(atom, config, file)

如果您查看 ProjectStack 的来源模块你可以观察到它是一个基于 Agent 的状态机.所以基本上所有的 mix 项目都被压入堆栈,并且可以检查它们是否有重复的名称。

关于elixir - 什么时候应该在 .exs 文件中使用 defmodule,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58698959/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com