You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clojure默认参数函数非惰性执行问题及解决方法问询

问题原因

Clojure中,函数参数解构时:or映射内的默认值会在函数调用阶段立即求值,无论你是否传入了对应的参数。也就是说,调用(hello :a 22)时,Clojure会先执行:or里的(mycall),之后才会用传入的:a 22覆盖这个默认值,所以你会看到*** called的输出。

实现方案(仅未传参时执行默认函数)

把默认值的逻辑移到函数体内处理,而非放在:or解构规则中,以下是几种可行方式:

方式一:手动检查参数存在性

(defn mycall[]
  (print "*** called")
  100)

(defn hello [& opts]
  (let [{:keys [a]} opts
        a (if (contains? opts :a) a (mycall))]
    (print a)))

测试效果:

(hello :a 22) ; 输出 22,无*** called
(hello)       ; 输出 *** called 和 100

方式二:用get函数简化逻辑

get函数仅当目标键不存在时,才会求值默认表达式,写法更简洁:

(defn hello [& opts]
  (let [a (get opts :a (mycall))]
    (print a)))

效果和方式一完全一致。

方式三:fnil包装(适合函数型默认值)

如果默认逻辑是函数,可通过fnil实现“值不存在时调用默认函数”的逻辑:

(defn hello [& opts]
  (let [a ((fnil identity mycall) (:a opts))]
    (print a)))

fnil会在(:a opts)为nil时执行mycall,否则直接返回参数值。

内容的提问来源于stack exchange,提问作者dedupe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:07:28