我能理解这一点:
iex(7)> outside_val = 5
5
iex(8)> print = fn() -> IO.puts(outside_val) end
#Function<20.90072148/0 in :erl_eval.expr/5>
iex(9)> print.()
5
:ok
为什么Elixir不允许定义打印功能,即使未定义outside_val且仅在以后出错?没有办法传递&#39; outside_val&#39;无论如何已经定义了关闭之后,Elixir在创建期间检查变量是否存在更好?
我的意思是:
iex(2)> print = fn () -> IO.puts(outside_val) end
#Function<20.90072148/0 in :erl_eval.expr/5>
iex(3)> outside_val = 5
5
iex(4)> print.()
** (RuntimeError) undefined function: outside_val/0
答案 0 :(得分:10)
这是Elixir中的一个错误,它将在v1.1中修复(已在主分支中):
Interactive Elixir (1.1.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> print = fn () -> IO.puts(outside_val) end
** (CompileError) iex:1: undefined function outside_val/0
当前实现延迟扩展以调用IEx.Helpers
中的函数。在master中,我们只需导入IEx.Helpers
,因此我们不再需要稍后展开outside_val
。
答案 1 :(得分:3)
在Erlang中定义一个函数时有很多步骤(在Elixir中,因为它构建在ErlangVM之上)。
首先,您将输入标记为:
{ok, Ts, _} = erl_scan:string("fun() -> Z + 1 end.").
然后,您创建抽象语法树:
{ok, [ListAST]} = erl_parse:parse_exprs(Ts).
最后一步是评估它:
Bindings = [{'Z', 1}].
erl_eval:expr(ListAST, Bindings).
在最后一步中,Erlang可以看到,存在未定义的变量并引发异常。
在Elixir中,大多数语言功能都是作为宏实现的,因此在函数定义期间不会采用最后一步,而是在调用它时。我不确定,如果能够检查,是否所有变量都绑定在宏定义中。如果有可能 - 那将是很酷的解决方案。