2015-02-09 90 views
5

我能理解這一點:爲什麼Elixir允許使用未定義變量的閉包?

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 

我沒有得到這麼多的是,爲什麼是它允許藥劑即使outside_val沒有定義要定義的打印功能和唯一的錯誤出來以後?無論如何,在關閉被定義之後,沒有辦法傳入'outside_val',所以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

這是任何REPL中對於動態語言(例如我曾經使用過的Elixir)的常見行爲(實際上並非如此)。也就是說,我在'Clojure'的'lein repl'中看到了相同的結果。 – ThanksForAllTheFish 2015-02-09 08:03:57

回答

10

這是在藥劑中的錯誤將被固定在1.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

3

有幾個步驟,確定在二郎山函數時(和藥劑,因爲它是建立在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中,大多數語言特性都是作爲宏來實現的,所以最後一步不是在函數定義期間,而是在調用時。我不確定,如果你能夠檢查,如果所有變量都被綁定在宏定義中。如果可能的話 - 那將是一個很酷的解決方案。

相關問題