7

我想找到 elisp 的类似物:

sum(n for n in numbers if n % 2) # Python
numbers.select { |n| n % 2 != 0 }.inject { |a, b| a + b } # Ruby

命令方式:

(defun oddp (number)
  (not (= (mod number 2) 0)))

(defun sum-odd-with-dolist (list)
  (let ((acc 0))
    (dolist (item list acc)
      (if (oddp item)
          (setq acc (+ item acc))))))

移植 Common Lisp

(defun sum-odd-with-dolist-incr (list)
  (let ((total 0)) 
    (dolist (item list) 
      (if (oddp item)
          (incf total item))) 
      total))

使用“ cl-*loop

(defun sum-odd-with-loop (list)
  (loop for x in list if (oddp x) sum x))

(sum-odd-with-loop '(1 2 3))
4

有没有更惯用的方法(不需要cl-*包)?

有关的:

如何对 Emacs Lisp 中的数字列表求和?

4

3 回答 3

14

惯用的方法是使用cl包中的函数和宏。它们是 Emacs Lisp 的标准配置,使用它们没有任何问题。

我怀疑你会找到一种简洁明了的方法

(loop for x in list if (oddp x) sum x)

还有更多功能性的方法可以做到这一点,例如

(apply #'+ (remove-if-not #'oddp list))

但这使用remove-if-not的是cl-seq包装中的。你可以手动写出一个循环:

(let ((sum 0)) (dolist (x list sum) (when (oddp x) (incf sum x))))

但这两种用途dolistincfcl-macs包装中。基本上你无法逃脱这个cl包:oddp它本身就是一个cl函数!

我完全不使用任何cl设施的最大努力是:

(apply #'+ (mapcar (lambda (x) (* x (mod x 2))) list))

但是在实践中使用它而不是(loop ...)版本是荒谬的。

于 2009-02-26T19:19:20.970 回答
6

(apply '+ (delq nil (mapcar (lambda (x) (and (= 1 (% x 2)) x)) '(1 2 3 4 5))))
于 2009-02-26T18:01:32.247 回答
2

我同意Gareth Rees 的回答,但如果您在代码中大量使用函数式编程和数据操作,我强烈建议您安装 Magnar Sveen 的dash.el列表 API。它有大量用于编写简洁优雅的函数式代码的函数。顺便说一句,它本身是在没有cl库的情况下编写的。总结一个列表中的奇数将是:

(-sum (--filter (= (mod it 2) 1) '(1 2 3 4 5)))

-sum是 的缩写(-reduce '+ xs)。以 2 个连字符开头的函数是照应宏,它们公开一个临时变量。例如,这里不是传递(lambda (x) (= (mod x 2) 1))--filter我们,而是简单地写(= (mod it 2) 1),其中it用于局部变量。

于 2014-03-18T11:14:04.607 回答