(常量x)与(fn [&_] x)有何不同?



我使用一种多方法来提供不同的功能,这取决于我的项目运行的"模式"(它是一个yadaapi服务器,应该能够在:dev:prod等模式下运行(。

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

(defstate mode :start :dev)

当我使用(constantly mode)进行调度时,会出现错误,但当我使用(fn [& _] mode)进行调度时似乎可以正常工作。

这两种形式不一样吗?或者在评估它们的方式(或时间(上是否存在一些细微的差异?

在装载中,如果尚未启动状态,则它们的值为DerefableState对象。

通过不断调用,您首先计算mode的值,然后用该值调用constantly函数。这意味着,当您调用constantly的结果时,它将始终返回的参数为,尽管您已经更改了它。如果您在调用constantly之前尚未启动状态,则它将存储DerefableObject

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

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

(defstate dispatch :start (constantly state))

我认为对于另一种解释,你可以使用副作用来突出区别

比较:

(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不是宏,因此必须首先计算它的参数。然而,fn是一个宏,因此它在计算参数之前运行。

最新更新