在 clojure 中,如何编写类似 defn 的宏,其中函数将在第一次失败时退出?

发布于 2025-01-08 22:01:45 字数 329 浏览 6 评论 0原文

在 clojure 中,我想编写一个 defn-my 宏来创建一个带有 body 的函数。当执行此函数时,它会在第一个不返回 0 的语句处退出。

例如:

(defn f1[] (println "f1") 5)
(defn f2[] (println "f2") 0)
(defn-my foo[] (f1) (f2))     
(defn-my bar[] (f2) (f1))
(foo); should execute f1 and exit
(bar); should execute f2 and then f1

In clojure, I would like to write a defn-my macro that creates a function with a body. And when this function is executed, it exits on first statement that doesn't return 0.

For example:

(defn f1[] (println "f1") 5)
(defn f2[] (println "f2") 0)
(defn-my foo[] (f1) (f2))     
(defn-my bar[] (f2) (f1))
(foo); should execute f1 and exit
(bar); should execute f2 and then f1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨夜星沙 2025-01-15 22:01:45

我认为您要求的是这样的:

(defmacro and-zero
  ([] true)
  ([x] (zero? x))
  ([x & next] 
    `(let [and# (zero? ~x)]
       (if and# 
         (and-not-zero ~@next)
         and#))))

user=> (and-zero 0 0 0)
true
user=> (and-zero 0 1 0)
false

宏假设每个表达式的计算结果都是一个数字。例如,如果表达式的计算结果为nil,它将引发异常。

然后你可以这样写defn-my

(defmacro defn-my [ & body ] `(and-zero ~@body))

I think you are asking for something like this:

(defmacro and-zero
  ([] true)
  ([x] (zero? x))
  ([x & next] 
    `(let [and# (zero? ~x)]
       (if and# 
         (and-not-zero ~@next)
         and#))))

user=> (and-zero 0 0 0)
true
user=> (and-zero 0 1 0)
false

The macro assumes every expression evaluates to a number. It will throw an exception if, for example, an expression evaluates to nil.

Then you can write yout defn-my like this:

(defmacro defn-my [ & body ] `(and-zero ~@body))
黯淡〆 2025-01-15 22:01:45

只需利用 and 的短路行为即可:

(defn foo []
  (and (f1) (f2)))

(defn bar []
  (and (f2) (f1)))

结果:

user=> (foo)
f1
nil
user=> (bar)
f2
f1
nil

使用 or 可以获得相反的行为,在第一个非零处终止。

Just leverage the short-circuit behaviour of and:

(defn foo []
  (and (f1) (f2)))

(defn bar []
  (and (f2) (f1)))

Results:

user=> (foo)
f1
nil
user=> (bar)
f2
f1
nil

You can get the opposite behaviour, terminating on first non-nil, with or.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文