我正在尝试创建一个使用apply和mapcar来计算它的函数。
在使用第一张mapcar获取列表中p-q的所有差异后,我陷入困境。如何平方列表中的所有元素并将它们相加?
(defun euclidean-distance-map (p q)
;; get a list of differences of p - q
(mapcar #'- p q))
答案 0 :(得分:7)
如果你真的需要坚持使用HOF(reduce
& mapcar
),那么这里有几个选择:
(defun euclidean-distance-map (p q)
(let ((d (mapcar #'- p q))) ; get a list of differences of p & q
(sqrt (reduce #'+ (mapcar #'* d d)))))
(defun euclidean-distance-map (p q)
(sqrt (reduce #'+ (mapcar (lambda (x) (* x x)) (mapcar #'- p q)))))
(defun euclidean-distance-map (p q)
(sqrt (reduce #'+ (mapcar (lambda (x y)
(let ((d (- x y)))
(* d d)))
p q))))
apply
vs reduce
使用apply
代替reduce
是一个错误的想法(因为call-arguments-limit
和风格),但是你走了:
(defun euclidean-distance-map (p q)
(let ((d (mapcar #'- p q))) ; get a list of differences of p & q
(sqrt (apply #'+ (mapcar #'* d d)))))
(defun euclidean-distance-map (p q)
(sqrt (apply #'+ (mapcar (lambda (x) (* x x)) (mapcar #'- p q)))))
(defun euclidean-distance-map (p q)
(sqrt (apply #'+ (mapcar (lambda (x y)
(let ((d (- x y)))
(* d d)))
p q))))
如果没有众所周知的“足够智能的编译器”,mapcar
会分配立即丢弃的存储空间。
这可能不一定是现代世代GC的问题。
请注意,使用loop
的迭代版本同样明确:
(defun euclidean-distance-map (p q)
(sqrt (loop for x in p
and y in q
for d = (- x y)
sum (* d d))))
Lisp是一种多范式语言,您不必强迫自己进入specific框架。
答案 1 :(得分:2)
(sqrt .)
.
,我们需要总结平方差异。这里apply
将完成工作。我们想要(+ a1 a2 a3 ...)
,问题是我们不知道要添加多少项。假设这些项目可以放入列表中,可以(apply #'+ .)
。所以,到目前为止,我们已经(sqrt (apply #'+ .))
。mapcar
:(mapcar (lambda (x) (* x x)) .)
。(mapcar #'- u v)
。总的来说,
(defun euclidian-distance (u v)
(sqrt (apply #'+ (mapcar (lambda (x) (* x x)) (mapcar #'- u v)))))
> (euclidian-distance '(1 4 3) '(1 1 -1))
> 5.0
答案 2 :(得分:1)
这是一个使用高阶函数的变体,并没有为差异分配列表:
(defun euclidian-distance (u v)
(let ((sum 0.0))
(mapc (lambda (x y)
(let ((d (- x y)))
(incf sum (* d d))))
u
v)
(sqrt sum)))