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

我的ClojureScript宏无法运行?需实现类似when-let的when-not-empty-let宏

问题分析与修复方案

你的when-not-empty-let宏无法正常工作,主要有两个关键问题,我来逐一拆解:

1. 宏定义中存在展开阶段的副作用

你在宏体里直接写了(.log js/console "check"),这段代码会在宏被加载/定义的时候就执行,而不是当你调用when-not-empty-let的时候执行。这不仅会导致意外的控制台输出,还会干扰宏的正常展开逻辑——宏的核心职责是生成目标代码,而非直接执行副作用代码。

2. 绑定处理的健壮性不足(次要问题)

虽然原when-let也只支持单个[binding-form expr]格式的绑定,但你的代码没有对bindings的格式做校验,如果用户传入不符合要求的参数(比如空列表、多组绑定),会抛出难以排查的错误。


修复后的宏代码

我移除了干扰性的副作用代码,保留了核心逻辑,同时添加了和原when-let对齐的参数格式校验:

(defmacro when-not-empty-let
  "bindings => binding-form test
   When test is not empty, evaluates body with binding-form bound to the value of test"
  [bindings & body]
  (if (vector? bindings)
    (let [form (first bindings)
          tst (second bindings)]
      `(let [temp# ~tst]
         (when (not-empty temp#)
           (let [~form temp#]
             ~@body))))
    (throw (IllegalArgumentException.
            "bindings must be a vector of the form [binding-form expr]"))))

验证示例

调用修复后的宏测试效果:

;; 非空集合,会执行body逻辑
(when-not-empty-let [xs [1 2 3]]
  (println "Got non-empty collection:" xs))
;; 输出: Got non-empty collection: [1 2 3]

;; 空集合,不会执行body逻辑
(when-not-empty-let [xs []]
  (println "This won't print"))
;; 无输出

如果你确实需要在运行时打印日志,可以把日志代码放到when块内部(运行时执行),比如:

(defmacro when-not-empty-let
  "bindings => binding-form test
   When test is not empty, evaluates body with binding-form bound to the value of test"
  [bindings & body]
  (if (vector? bindings)
    (let [form (first bindings)
          tst (second bindings)]
      `(let [temp# ~tst]
         (when (not-empty temp#)
           (.log js/console "check: got non-empty value" temp#)
           (let [~form temp#]
             ~@body))))
    (throw (IllegalArgumentException.
            "bindings must be a vector of the form [binding-form expr]"))))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:33:42