次の関数は、結果が fixnum に収まる fixnum 値でのみ呼び出されることを sbcl に伝えたかったのです。
(defun layer (x y z n)
(+ (* 2 (+ (* x y) (* y z) (* x z)))
(* 4 (+ x y z n -2) (1- n))))
私の最初の試みはすることでした
(defun layer (x y z n)
(declare (fixnum x y z n))
(the fixnum
(+ (* 2 (+ (* x y) (* y z) (* x z)))
(* 4 (+ x y z n -2) (1- n))))
しかし、sbcl が作成した非常に有用なコンパイル ノートを見て分かったように、その戻り値の型宣言は、すべての中間結果も fixnum になるとは約束していません。それで、私はこれをしました:
(defmacro fixnum+ (&rest args)
(reduce
(lambda (x y) `(the fixnum (+ ,x ,y)))
args))
(defmacro fixnum* (&rest args)
(reduce
(lambda (x y) `(the fixnum (* ,x ,y)))
args))
(defun layer (x y z n)
(declare (fixnum x y z n))
(fixnum+ (fixnum* 2 (fixnum+ (fixnum* x y) (fixnum* y z) (fixnum* x z)))
(fixnum* 4 (fixnum+ x y z n -2) (the fixnum (1- n)))))
そして、それはうまくいきました。私の質問は、これを行うためのより簡単で慣用的な方法はありますか?
たとえば、+、-、*、1- の型を再宣言して、fixnum の結果を保証することはできますか? (一般的には悪い考えだとはわかっていますが、特定のプログラムでやりたいと思うかもしれません。) CHICKEN スキームは、私が望むことを行います。(declare (fixnum-arithmetic))
(安全ではありませんが)fixnum に対するすべての算術演算の結果が fixnum であると仮定します。