(恒定x)与(fn [&_] x)有何不同?

时间:2018-07-21 04:59:53

标签: clojure expression-evaluation

我正在使用多种方法来提供不同的功能,具体取决于我的项目在哪种“模式”下运行(这是yada api服务器,应该可以在:dev,{{ 1}}模式等。

我正在使用mount/defstate提供一个关键字:

:prod

当我使用(defstate mode :start :dev) 进行分派时,会出现错误,但是当我使用(constantly mode)进行分派时,它似乎可以正常工作。

这两种形式不一样吗?还是在评估方式(或时间)上有一些细微的差异?

2 个答案:

答案 0 :(得分:5)

mount中,如果您尚未启动状态,则其值为DerefableState对象。

通过调用constantly,您首先评估mode的值,然后使用该值调用constantly函数。这意味着,当您调用constantly的结果时,尽管此后您对其进行了更改,它始终将始终返回常量的参数。如果您在调用constantly之前尚未开始状态,则它将存储DerefableObject

另一方面,对于(fn [& _] mode),您每次调用函数时都会评估mode var的值。如果您还没有开始自己的状态,那么它还将返回一个DerefableState,但是如果您已经开始,那么结果将是预期的关键字。

一个简单的解决方案是将调度功能也置于一种状态。

(defstate dispatch :start (constantly state))

答案 1 :(得分:3)

我想作为替代解释,您可以使用副作用来突出说明区别。

比较:

text

仅执行第一个(def const-f (constantly (println "Hello!"))) Hello! => #'user/const-f (def fn-f (fn [] (println "World!"))) => #'user/fn-f 就会导致def被打印,因为Hello!的主体会被立即求值。但是,第二个constantly不会打印任何内容,因为def的主体没有被评估。

尽管打电话给他们

fn

(const-f) => nil ; Prints nothing. Just evaluates to what println returned (fn-f) World! ; Prints now, => nil ; then returns what println evaluates to 不是宏,因此必须首先对它的参数求值。 constantly 宏,因此在其参数求值之前运行。