我正在學習從Practical Common Lisp的Common Lisp。它具有讀取和第24章寫二進制文件下面是一個例子輔助函數的例子:如何在Common Lisp中編寫類似的函數?
(defun read-u2 (in)
(+ (* (read-byte in) 256) (read-byte in)))
我可以寫功能同樣讀其他類型的二進制數。但我認爲這樣做違反了DRY原則。此外,這些函數將會類似,所以我試圖用宏來生成函數。
(defmacro make-read (n be)
`(defun ,(intern (format nil "READ~d~:[L~;B~]E" n be))
(&optional (stream *standard-input*))
(logior ,@(loop for i from 0 below n collect
`(ash (read-byte stream)
,(* 8 (if be (- n 1 i) i)))))))
(defmacro make-read-s (n be)
`(defun ,(intern (format nil "READ~d~:[L~;B~]E-S" n be))
(&optional (stream *standard-input*))
(let ((a (,(intern (format nil "READ~d~:[L~;B~]E" n be)) stream)))
(if (zerop (logand a ,(ash 1 (1- (* 8 n)))))
a
(logior a ,(ash -1 (* 8 n)))))))
(defmacro make-write (n be)
`(defun ,(intern (format nil "WRITE~d~:[L~;B~]E" n be))
(n &optional (stream *standard-output*))
(setf n (logand n ,(1- (ash 1 (* 8 n)))))
,@(loop for i from 0 below n collect
`(write-byte (ldb (byte 8 ,(* 8 (if be (- n 1 i) i))) n)
stream))))
(eval-when (:compile-toplevel :load-toplevel :execute)
(dolist (cat '("READ" "READ-S" "WRITE"))
(dolist (be '(nil t))
(dolist (n '(1 2 4 8))
(eval `(,(intern (format nil "MAKE-~a" cat)) ,n ,be))))))
它的工作原理。它生成讀取和寫入大小爲1,2,4和8的無符號和有符號整數的函數。SLIME理解它。但我想知道是否有更好的方法。
在Common Lisp中編寫一堆類似函數的最好方法是什麼?
爲什麼不使用'&optional'?如果是爲了提高效率,如果功能是內聯的,它是否仍然適用? – nisekgao
@nisekgao:看我的編輯。 –