【问题标题】:Summing vectors with common lisp 'loop' macro用常见的 lisp 'loop' 宏对向量求和
【发布时间】:2013-01-25 23:00:58
【问题描述】:

我需要实现这样的东西:

(loop for i from 1 to N sum (f i))

除了累积值表示数字列表,如 (1 2 3) 并且它们是按元素添加的。换句话说,我想初始化求和 使用 (zerov N) 并使用 (v+) 添加后续元素:

(defun v+ (a b) (mapcar '+ a b))
(defun zerov (n) (loop for i from 1 to n collect 0))

可以用循环宏做这样的事情吗?我可以将它实现为 单独的函数,但我想使用循环或类似循环的宏来表达。 也许有一种方法可以为这种情况定义简单的类似循环的宏?

【问题讨论】:

  • 标准 LOOP 没有为用户提供任何自定义操作的方法,但可能有特定于实现的扩展允许这样做(早期的 MacLisp LOOP 允许用户定义的运算符,并且某些实现可能有建立在该代码之上)。
  • 我正在使用 CCL。我没有看到任何我可以使用的东西。
  • (mapcar + a b)` 可以立即识别。但是,它将向量的表示提交给列表。最好的办法是抽象矢量 API 背后的矢量操作。在您自己的包中,您可以将 + 运算符绑定到可以添加两个向量的函数(并且仍然适用于数字,可能还有数字和向量的组合)。

标签: loops lisp common-lisp


【解决方案1】:
(loop with accum = (make-list n :initial-element 0)
      for i from 1 to n
    do (setq accum (v+ accum (f i)))
  finally (return accum))

【讨论】:

  • 谢谢!看起来您在“do”行缺少右括号
【解决方案2】:

Common Lisp 标准中定义的LOOP 不可扩展。

我会用普通的 LOOP 功能编写它:

(let ((result (zerov n)))
  (loop for i from 1 to N
        do (setf result (v+ result (f i))))
  result)

我会把它写成一个函数:

(defun sum (n f init sum)
  (let ((result (funcall init n)))
    (loop for i from 1 to n
          do (setf result (funcall sum result (funcall f i))))
    result))

如果您想要像循环宏的直接语言功能这样的功能,那么替代方法是ITERATE 宏,它比 LOOP 宏更强大,而且还具有可扩展性。

【讨论】:

  • 谢谢!我想到了这个解决方案。问的可能太多了,但是我来自 Haskell 世界,并且会更喜欢纯功能解决方案,例如高级 reduce...
  • @krokodil:在 Common Lisp 中使用 CL:REDUCE 是没有意义的。最好坚持使用循环实现并将其作为函数提供。
  • @krokodil:给定你对v+的定义,以及一个合适的范围定义,你可以写成(reduce #'v+ (mapcar #'f (range 1 n)))
【解决方案3】:
(reduce #'v+ (loop for i from 1 to n collect (f i))
        :initial-value (zerov n))

请注意,Common Lisp 具有适当的“向量”(即,同质类型的元素序列允许更紧凑的表示和有效的随机访问),所以也许,

(defun v+ (a b) (map-into a #'+ a b))
(defun zerov (n) (make-array n :initial-element 0))
(defun fn (i n) (let ((v (zerov n))) (setf (aref v i) 1) v))
(defun gn (n)
  (loop for v = (zerov n) then (v+ v (fn i n)) for i below n
        finally (return v)))

【讨论】:

  • REDUCE 的问题在于 Lisp 中的列表不是惰性的,需要通过完整的列表来减少。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多