出于安全原因,我拥有仅在开发环境中可用的功能。如果我做这样的事情:
if Mix.env() == :dev do
def some_func() do
do_sensitive_stuff()
end
end
编译项目时,if
块中的代码是否不会被编译?更一般而言,我可以像这样在编译时运行代码吗?还是我需要像宏这样的东西?
答案 0 :(得分:1)
Elixir实际上是在Erlang VM之上的一种DSL。域非常广泛,但仍然如此。 Elixir中的几乎所有东西都是宏。
def
,defmodule
,甚至defmacro
本身就是indeed a macro。
编译器的工作原理没有魔力。在第一阶段,它将遍历源代码并将所有内容转换为AST。当它看到宏时,将其展开(宏返回AST),并将返回的AST注入到恰好出现宏的位置。
在文件的顶层,defmodule
,defmodule
和def
等内可能都有一个代码。所有内容都将被扩展,直到无法进一步扩展为止。
当编译器看到if
时,它会扩展if
宏,但仍然没有魔术。
现在您可能会想知道为什么在编译阶段之后还剩下一些“可运行”的东西。当编译器看到def
或任何其他返回AST的宏时,它会存储该AST(然后该AST实际上会转换为BEAM文件。)
作为示例,您可以尝试以下代码:
defmodule Test do
IO.puts("I am compiling")
def run, do: IO.puts("I am running")
end
如果您尝试对其进行编译,则会看到以前的消息在编译阶段出现。后者只有在编译后显式调用Test.run/0
时才会出现。