无法推断此“的确切行号”;打印“U形块”;在Elixir中没有元编程的定义执行?
我正在使用Elixir…我发现,在定义以下没有宏的代码时,我必须将inspect无法推断此“的确切行号”;打印“U形块”;在Elixir中没有元编程的定义执行?,elixir,Elixir,我正在使用Elixir…我发现,在定义以下没有宏的代码时,我必须将inspect\uuuu ENV\uuuu放入,然后从打印的行号中减去2,以获得运行打印块的行号 h1 do h2 do print_block "prints message" do IO.puts "hello world!" IO.inspect(__ENV__) end end end 打印块的函数定义如下所示: def print_block(_msg, do: code
\uuuu ENV\uuuu
放入,然后从打印的行号中减去2,以获得运行打印块的行号
h1 do
h2 do
print_block "prints message" do
IO.puts "hello world!"
IO.inspect(__ENV__)
end
end
end
打印块的函数定义如下所示:
def print_block(_msg, do: code_block), do: code_block
类似的代码定义了h1和h2块
现在,如果我将h1
、h2
和print\u block
定义为宏,我可以通过遍历检查code\u block
时生成的AST,获得现有文件中print\u block
的准确行号
defmacro print_block(_msg, do: code_block) do
IO.inspect(code_block)
code_block
end
因为Elixir元编程允许您检查AST,所以在不使用“减去某个数字”的情况下精确匹配print_块的行号的唯一方法是通过宏定义它。你不能用传统的运行时模块/函数来实现,对吗?很确定是这样的,只是想确认一下
因为Elixir元编程允许您检查AST[…]
事实并非如此。宏所做的就是在编译之前在调用的位置注入AST。编译后的代码没有任何宏的踪迹,它们都消失了,被编译阶段返回的AST替代
这意味着您的宏无法按预期工作<代码>IO.inspect
在编译阶段执行。光束不会打印出任何内容,也不会有任何\uuuuu ENV\uuuu.line
或类似可访问的内容
OTOH有一个专门的location::keep
选项来保存文件和行号。它不会在开箱即用的情况下自动发生
此外,还有一个模块属性可以放入模块中,以指定哪些函数应该内联;基本上,内联的作用与调用宏几乎相同
我无法理解您所追求的确切目标是什么,但认为宏可以神奇地帮助您确定确切的行号的假设是完全错误的
这里演示了从
\uuuu ENV\uuuu
获取一行代码的所有可能性:
bat /tmp/foo.ex
───────┬───────────────────────────────────────────────────────────────────
│ File: /tmp/foo.ex
───────┼───────────────────────────────────────────────────────────────────
1 │ defmodule Foo do
2 │ @compile {:inline, print_block_inline: 2}
3 │
4 │ def print_block_inline(_msg, do: code_block), do: code_block
5 │ def print_block_normal(_msg, do: code_block), do: code_block
6 │ defmacro print_block_macro(_msg, do: code_block), do: code_block
7 │
8 │ def test do
9 │ print_block_normal "prints message" do
10 │ IO.puts("hello world!")
11 │ IO.inspect(__ENV__.line, label: "11")
12 │ end
13 │
14 │ print_block_inline "prints message" do
15 │ IO.puts("hello world!")
16 │ IO.inspect(__ENV__.line, label: "16")
17 │ end
18 │
19 │ print_block_macro "prints message" do
20 │ IO.puts("hello world!")
21 │ IO.inspect(__ENV__.line, label: "21")
22 │ end
23 │ end
24 │ end
25 │
26 │ Foo.test()
所有内容都已成功打印
elixir /tmp/foo.ex
hello world!
11: 11
hello world!
16: 16
hello world!
21: 21
谢谢@Alexsei,我只是想理解为什么我在对诸如print_block这样的宏定义函数执行IO.inspect(代码块)时得到了类似
[line:13],“hello world”]},
(为清晰起见缩写)。第13行是IO.puts(“hello world”)所在文件中的确切数字。我不认为用非宏函数就可以做到这一点?