常见的lisp新手。编写lisp代码与编写c ++ / java完全不同,正如我之前编写的那样。
我正在尝试在常见的lisp中编写一个简单的矩阵类来进行练习。有些代码是这样的:
(defun make-matrix (row col)
(make-list row :initial-element (make-list col :initial-element nil)))
(defun init-matrix (matrix init-value)
(labels ((set-element-value (lst)
(if (and lst
(listp lst))
(mapcar #'set-element-value lst)
(setf lst init-value))))
(set-element-value matrix)))
(defun matrix+ (&rest matrices)
(apply #'mapcar (lambda (&rest rows)
(apply #'mapcar #'+ rows)) matrices))
我的问题是我可以写一个矩阵+接受不同数量的参数而不用'apply',或以更好的方式?以某种方式,lisp应该是?
那么矩阵*怎么样,有人能给我看一些接受矩阵*中任意数量的参数的很棒的代码吗?感谢。
答案 0 :(得分:6)
Common Lisp有n维数组。我会将它们用于矩阵运算。
请参阅:MAKE-ARRAY
,AREF
,...
通常我也会编写一个二进制(采用两个参数)矩阵运算。然后使用REDUCE
操作矩阵列表。
CL-USER > (make-array '(3 5) :initial-element 0)
#2A((0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0))
Above创建一个大小为3x5的二维数组,其中0为初始内容。
答案 1 :(得分:3)
矩阵乘法。我不能保证这是最好的例子,但它确实是直截了当的。这是使用数组而不是列表。当然,您也可以针对方形矩阵或特殊情况(如标识矩阵等)进行优化。但这只是为了简单,效率低等。
(defun matrix* (&rest matrices)
(assert (cdr matrices) nil
"You will achieve nothing by multiplying a single matrix.")
(reduce
#'(lambda (a b)
(assert (= (array-dimension a 0) (array-dimension b 1)) nil
"The number of rows in the first matrix should be the number ~
of columns in the second matrix")
(let ((result
(make-array
(list (array-dimension a 1) (array-dimension b 0))
:initial-element 0)))
(dotimes (i (array-dimension a 1) result)
(dotimes (j (array-dimension b 0))
(dotimes (k (array-dimension a 0))
(incf (aref result i j) (* (aref a k i) (aref b j k))))))))
matrices))
(format t "result: ~s~&" (matrix* #2A((1 2) (3 4)) #2A((5 6) (7 8))))
;; #2A((23 31) (34 46)) =
;; (1 * 5 + 3 * 6 = 23) (1 * 7 + 3 * 8 = 31)
;; (2 * 5 + 4 * 6 = 34) (2 * 7 + 4 * 8 = 46)