2017-06-09 38 views
2

下面的代碼顯示了我詢問的一個例子: 爲什麼Map,Enum等...不能在guard子句中或在我自己的宏中使用。爲什麼我們不能在Elixir guard子句或宏中使用其他函數?

defmodule GuardMod do 
    defmacro has_any_key(arg, keys) do 
     quote do 
      Map.keys(unquote(arg), unquote(keys)) |> Enum.any? 
     end 
    end 
end 

defmodule OtherMod do 
    import GuardMod 

    @doc """ 
    has_any_key/2 is allowed, but Map.keys or Map.any not 
    """ 
    def fn1(list) when has_any_key(list, [:key1, :key2]), do: :nothing 
end 
+0

這個問題的答案是相關的:https://stackoverflow.com/questions/11177109/can-i-make-my-own-guards-in-erlang – Dogbert

+0

它是有道理的,因爲藥劑師和Erlang衛兵是相同的實現。 –

回答

3

這是一個妥協,讓多功能頭調度「快」。

警衛所允許的功能類型都具有有限的運行時間或減少計數。如果你在守衛中允許任意函數,你必須處理在當前進程超過當前執行片段之前守護評估沒有完成的情況。 (或者可能更糟糕的情況是競爭條件,因爲它需要來自另一個進程的輸入)。

+0

我讀過這篇文章http://keathley.io/2016/04/09/elixir-guard-clauses.html,它完美地回答了我的問題,正是你說的。防衛隊​​僅限於某些確保「純潔」的特定功能,並且沒有副作用,比如競賽條件。 –

+0

儘管「長度/ 1」,警衛還是有一個緩慢的功能。喜歡答案[這裏](https://stackoverflow.com/questions/11177109/can-i-make-my-own-guards-in-erlang)說,主要原因是函數應該是純粹的,它應該是好吧,忽略他們提出的錯誤。 Erlang/Elixir不允許將用戶定義的函數標記爲pure/ok來忽略錯誤,因此您只能使用列入白名單的函數。 – Dogbert

相關問題