懒惰的Elixir表达评估

时间:2015-02-24 20:18:36

标签: clojure elixir lazy-evaluation

我试图弄清楚在clojure中是否存在类似于delay的宏来获取可以在以后评估的惰性表达式/变量。

用例是Map.get/3的默认值,因为默认值来自数据库调用,我更喜欢只在需要时调用它。

5 个答案:

答案 0 :(得分:1)

默认值可以是进行昂贵呼叫的功能。如果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模块。虽然我不知道它有助于解决您的特定问题但它确实允许进行惰性评估。来自文档:

  

Streams是可组合的,懒惰的枚举。在枚举期间逐个生成项的任何可枚举称为流。例如,Elixir的Range是一个流:

文档中提供了更多信息:http://elixir-lang.org/docs/master/elixir/Stream.html

答案 1 :(得分:1)

Elixir的宏可用于编写简单的包装函数以进行条件评估。我在下面列出了一个要点,尽管它可能更好/更聪明。

https://gist.github.com/parroty/98a68f2e8a735434bd60

答案 2 :(得分:1)

Map.get_lazyKeyword.get_lazy 推迟生成默认值直到需要,链接下面的文档

https://hexdocs.pm/elixir/Map.html#get_lazy/3

https://hexdocs.pm/elixir/Keyword.html#get_lazy/3

答案 3 :(得分:0)

执行此操作的一种方法是使用流程。例如,地图可以包含在像GenServer或代理(http://elixir-lang.org/docs/v1.0/elixir/Agent.html)这样的流程中,其中默认值将被评估为惰性。

答案 4 :(得分:0)

“通用”懒惰是一个难以破解的难题,因为它是一个相当广泛的问题。 Streams允许对可枚举的懒惰,但我不确定表达式的懒惰意味着什么。例如,x = 1 + 2的懒惰形式是什么?什么时候评估?

表达式的懒惰形式的想法是一个过程表达式:

def x, do: 1 + 2

因为在实际调用表达式之前不会计算x的值(据我所知)。如果我在这一点上错了,我相信别人会纠正我。但我不认为这就是你想要的。

也许你想重新解释一下你的问题 - 省略流和对枚举值的惰性评估。