Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 长生不老药中表达的惰性评价_Clojure_Elixir_Lazy Evaluation - Fatal编程技术网

Clojure 长生不老药中表达的惰性评价

Clojure 长生不老药中表达的惰性评价,clojure,elixir,lazy-evaluation,Clojure,Elixir,Lazy Evaluation,我试图弄清楚clojure中是否有类似于delay的宏,以获得一个可以稍后计算的惰性表达式/变量 用例是Map.get/3的默认值,因为默认值来自数据库调用,所以我更希望只在需要时调用它。一种方法是使用进程。例如,映射可以包装在一个进程中,比如GenServer或一个将对默认值进行延迟计算的进程。默认值可以是一个进行昂贵调用的函数。如果没有使用Map.get/3返回函数,则可以检查该值是否为函数,并在返回时调用它。像这样: def default_value() expensive_db_c

我试图弄清楚clojure中是否有类似于
delay
的宏,以获得一个可以稍后计算的惰性表达式/变量


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

一种方法是使用进程。例如,映射可以包装在一个进程中,比如GenServer或一个将对默认值进行延迟计算的进程。

默认值可以是一个进行昂贵调用的函数。如果没有使用
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的流模块。虽然我不知道它是否有助于解决您的特定问题,但它确实允许延迟评估。从文件中:

流是可组合的惰性枚举。在枚举期间逐个生成项的任何可枚举项都称为流。例如,Elixir的范围是一条流:


有关详细信息,请参见。

Elixir的宏可用于编写用于条件求值的简单包装函数。我在下面列出了一个要点,尽管这可能是更好/更聪明的方法

“一般”懒惰是一个很难解决的问题,因为这是一个相当广泛的问题。流允许枚举的惰性,但我不确定表达式的惰性意味着什么。例如,
x=1+2
的惰性形式是什么?何时进行评估

对于表达式的惰性形式,我想到的是过程表达式:

def x, do: 1 + 2
因为直到表达式被实际调用(据我所知),x的值才被计算出来。如果我在这一点上错了,我相信其他人会纠正我。但我不认为那是你想要的


也许你想重新表述你的问题——省去流和枚举值的惰性计算。

Map.get_lazy
关键字。get_lazy
在需要之前不要生成默认值,链接下面的文档


这也是我最终得到的解决方案,尽管我的代码使用的是if-else,看起来不太好看。似乎没有更好的方法,除非我们真正得到了编译器支持:-),与clojure中的
delay
相比,clojure的一个缺点是,我们必须为我们想要使用的每个函数编写一个宏,而不是有一个通用运算符。Stream不是我想要的,我在寻找一种方法来推迟任何武断的表达。您使用
case
的解决方案与实际解决方案非常接近,但解决方案需要使用宏来处理任意表达式。我不太明白如何使用进程进行惰性求值,您介意举一些代码作为示例吗?查看Clojure中“延迟”的源代码(此处:)看起来延迟更接近于协议而不是宏。如果我是你,我会用长生不老药研究协议,并以那种方式继续。在提出问题之前,我检查了
delay
源代码,有趣的是
delay
是用java实现的,而不是clojure,它允许对表达式进行非常不同的构造和操作。