これは(これはwhat is to append as push is to cons, in Lisp?define-modify-macro
でも説明されていますが、現在のケースはより単純です) の良い使用例です。まず、制限付き合計を関数として記述します。これは非常に簡単です。と を取り、それらの合計が より大きい場合はを返し、そうでない場合はそれらの合計を返します。あなたが投稿した疑似コードとLispコードに基づいて、これは次のようになります。val
delta
1.0
1.0
(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)
マクロは最初の引数として場所を取り、2 番目の引数としてデルタを取ります。プレースから安全に値を取得し、sum-bounded
その値とデルタを使用して計算し、結果をプレースに格納します。ここで「安全に」とは、Lars Brinkhoff が賢明にも. 次に、それを使用します:
(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)