无法推断此“的确切行号”;打印“U形块”;在Elixir中没有元编程的定义执行?

无法推断此“的确切行号”;打印“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

我正在使用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_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”)所在文件中的确切数字。我不认为用非宏函数就可以做到这一点?