我试图弄清楚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