我試圖弄清楚clojure中是否有類似於delay
的宏以獲得可以稍後評估的懶惰表達式/變量。Elixir中表達式的懶惰評估
用例是Map.get/3
的默認值,因爲默認值來自數據庫調用,所以我寧願只在需要時才調用它。
我試圖弄清楚clojure中是否有類似於delay
的宏以獲得可以稍後評估的懶惰表達式/變量。Elixir中表達式的懶惰評估
用例是Map.get/3
的默認值,因爲默認值來自數據庫調用,所以我寧願只在需要時才調用它。
藥劑的宏可用於編寫簡單的包裝功能,有條件的評價。我已經在下面提出了一個要點,雖然它可能是更好/更聰明的方式。
這也是我最終得到的解決方案,雖然我的代碼使用if else,看起來好多了。 好像有沒有更好的辦法,除非我們實際上得到的編譯器支持:-) 而一個缺點比較'delay'在Clojure是,我們必須寫我們要利用一切功能的宏,而不是有一個通用運營商。 – NhanH 2015-02-25 01:02:22
執行此操作的一種方法是使用進程。例如,地圖可以封裝在GenServer或代理(http://elixir-lang.org/docs/v1.0/elixir/Agent.html)等進程中,其中默認值將被評估爲懶惰。
我不太關注你如何使用懶惰評估的過程,你介意把一些代碼作爲例子嗎? – NhanH 2015-02-25 01:06:12
默認值可以是一個功能,它使昂貴的通話。如果Map.get/3
未用於返回函數,則可以檢查該值是否爲函數,並在返回時調用它。像這樣:
def default_value()
expensive_db_call()
end
def get_something(dict, key) do
case Map.get(dict, key, default_value) do
value when is_fun(value) ->
value.() # invoke the default function and return the result of the call
value ->
value # key must have existed, return value
end
end
當然,如果地圖包含功能這種類型的解決方案可能不會工作。
另請檢查Elixir的Stream模塊。雖然我不知道它會幫助解決您的特定問題,但確實可以進行懶惰評估。從文檔:
流是可組合的,惰性枚舉。任何在枚舉過程中逐一生成項目的枚舉被稱爲流。例如,藥劑的範圍是流:
更多信息可在文檔中:http://elixir-lang.org/docs/master/elixir/Stream.html
流不是我正在尋找的,我正在尋找一種方式來延遲任何表達。 您使用'case'的解決方案非常接近實際的解決方案,但解決方案需要使用宏來處理任意的表達式。 – NhanH 2015-02-25 01:05:43
「通用」懶惰是有點難啃的打擊,因爲這是一個相當寬泛的問題。流允許懶惰的枚舉,但我不確定表達懶惰是什麼意思。例如,x = 1 + 2
的懶形式是什麼?何時進行評估?
該想到用於表達式的懶惰形式的思想是一個過程表達:
def x, do: 1 + 2
因爲x的值將不被計算,直到表達被實際調用(據我知道)。我相信如果我在這一點上錯了,其他人會糾正我。但我不認爲這就是你想要的。
也許你想要改寫你的問題 - 忽略流和對枚舉值的惰性評估。
查看源在Clojure的(這裏:https://github.com/clojure/clojure/blob/201a0dd9701e1a0ee3998431241388eb4a854ebf/src/jvm/clojure/lang/Delay.java)「延遲」它看起來像延遲接近到一個協議而不是一個宏。如果我是你,我會在Elixir中調查協議並以這種方式繼續。 – 2015-02-25 14:49:48
在問這個問題之前,我檢查了'delay'源,有趣的是'delay'是在java中實現的,而不是clojure--它允許對錶達式進行不同的構造和操作。 – NhanH 2015-02-25 23:14:40