gpt4 book ai didi

macros - 编写破坏性的宏或函数,如 incf?

转载 作者:太空宇宙 更新时间:2023-11-03 18:41:28 25 4
gpt4 key购买 nike

我需要一个 incf 函数,它在递增期间进行一些边界检查:

val := val + delta
if val >= 1.0
then return 1.0
else return val

我可以使用 incf 编写:

(defun incf-bounded(val delta)
(incf val delta)
(if (>= val 1.0) 1.0 val))

在这种情况下,我需要像 (setf x (incf-bounded x delta)) 这样使用它。但是我该如何编写一个我可以像 (incf-bounded x delta) 这样使用的代码,即 x 将被修改的地方?

最佳答案

这是 define-modify-macro 的一个很好的用例(在 what is to append as push is to cons, in Lisp? 中也有描述,但本例更简单)。首先,将你的有界和写成一个函数。这很简单;它接受 valdelta,如果它们的总和大于 1.0,则返回 1.0,否则返回它们的总和。根据您发布的伪代码和 Lisp 代码,这可能是:

(defun sum-bounded (val delta)
(if (>= (+ val delta) 1.0)
1.0
(+ val delta)))

实际上,为了计算这个值,您可以使用:

(defun sum-bounded (val delta)
(min 1.0 (+ val delta)))

现在您使用define-modify-macro 来定义宏incf-bounded:

(define-modify-macro incf-bounded (delta) sum-bounded)

宏将 place 作为第一个参数,delta 作为第二个参数。它安全地从位置检索值,使用该值和增量计算 sum-bounded,然后将结果存储回 place。这里的“安全”是指避免了多次求值可能出现的问题,如Lars Brinkhoff's wisely warns against .然后你就可以使用它了:

(let ((x .5))
(incf-bounded x .3)
(print x) ; prints 0.8
(incf-bounded x .3)
(print x)) ; prints 1.0 (not 1.1)

对于更复杂的情况,要修改的地方自然不是您想要的宏的第一个参数,您需要编写自己的宏并使用get-setf-expansion。 , 但这在

中有更详细的解释

一起编码以便于复制和粘贴

(defun sum-bounded (val delta)
"Returns the lesser of 1.0 or the sum of val and delta."
(min 1.0 (+ val delta)))

(define-modify-macro incf-bounded (delta) sum-bounded
"(incf-bounded place delta) computes the sum of the value of the
place and delta, and assigns the lesser of 1.0 and the sum of the value
and delta to place.")

(defun demo ()
(let ((x .5))
(incf-bounded x .3)
(print x) ; prints 0.8
(incf-bounded x .3)
(print x))) ; prints 1.0 (not 1.1)

关于macros - 编写破坏性的宏或函数,如 incf?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19485964/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com