我正在使用多种方法来提供不同的功能,具体取决于我的项目在哪种“模式”下运行(这是yada api服务器,应该可以在:dev
,{{ 1}}模式等。
我正在使用mount/defstate
提供一个关键字:
:prod
当我使用(defstate mode :start :dev)
进行分派时,会出现错误,但是当我使用(constantly mode)
进行分派时,它似乎可以正常工作。
这两种形式不一样吗?还是在评估方式(或时间)上有一些细微的差异?
答案 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
是 宏,因此在其参数求值之前运行。