Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros bind_quoted不会在def中创建绑定_Macros_Elixir - Fatal编程技术网

Macros bind_quoted不会在def中创建绑定

Macros bind_quoted不会在def中创建绑定,macros,elixir,Macros,Elixir,bind\u quoted似乎对我不起作用。下面是一个不使用bind_quoted的示例,它按预期工作: defmodule Animals do defmacro dog do x = 4 quote do def go do IO.puts unquote(x) end end end end defmodule Test do require Animals Animals.dog #inject

bind\u quoted
似乎对我不起作用。下面是一个不使用
bind_quoted
的示例,它按预期工作:

defmodule Animals do

  defmacro dog do
    x = 4 

    quote do
      def go do
        IO.puts unquote(x)
      end
    end

  end

end

defmodule Test do
  require Animals
  Animals.dog  #inject the definition of go() into the Test module
end
在iex中:

iex(10)> c "a.exs"
warning: redefining module Animals (current version defined in memory)
  a.exs:1

warning: redefining module Test (current version defined in memory)
  a.exs:15

[Test, Animals]

iex(11)> Test.go  
4
:ok

iex(12)>
但政府说:

…每次需要时,建议使用:bind_quoted选项 在报价中插入一个值

好吧,让我们保持一致:

defmodule Animals do

  defmacro dog do
    x = 4 

    quote bind_quoted: [x: x] do
      def go do
        IO.puts x
      end
    end

  end

end

defmodule Test do
  require Animals
  Animals.dog  #inject go() into the Test module
end
在iex中编译:

iex(10)> c "a.exs"
warning: redefining module Animals (current version defined in memory)
  a.exs:1

warning: redefining module Test (current version defined in memory)
  a.exs:15

warning: variable "x" does not exist and is being expanded to "x()", please use parentheses to remove the ambiguity or change the variable name
  a.exs:17


== Compilation error in file a.exs ==
** (CompileError) a.exs:17: undefined function x/0 
    (stdlib) lists.erl:1338: :lists.foreach/2
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
** (CompileError)  compile error
    (iex) lib/iex/helpers.ex:183: IEx.Helpers.c/2
iex(10)> 
错误报告中的相关消息为:

warning: variable "x" does not exist

为什么不呢?

通常是的。这就是它的工作原理。但是
def
调用本身是一个宏,因此您仍然需要在其内部使用
unquote
。如果您直接引用
IO.puts
,它将不会出现问题

下面是一个稍加修改的代码版本,演示了这一点:

def模块动物做什么
狗做什么
x=4
报价(bind_报价:[xx:x])do
IO.puts(xx)
终止
终止
终止
defmoduletestdo
需要动物
去做什么
动物,狗
终止
终止

现在回到您的实现;在本例中,我将
x
绑定到
xx
以明确显示,如果您尝试在此处取消引用
x
(而不是
xx
),它将抛出编译错误:

def模块动物做什么
狗做什么
x=4
报价(bind_报价:[xx:x])do
去做什么
IO.puts(不引用(xx))
终止
终止
终止
终止

如果您尝试在此处取消引用x(而不是xx),它将抛出编译错误
--嗯……这很有趣。
bind\u quoted
的工作方式比文档中介绍的要复杂得多。我真的不明白为什么
bind\u quoted
不只是替换ast中找到的关键字的所有实例。我猜规则是:
bind\u quoted
不会在嵌套宏中创建绑定,例如在这种情况下,
def
;并且def块只能在直接包围的do块中看到绑定,因此def的do块可以看到xx而不能看到x。