Emacs Lisp: как суммировать нечетные числа в списке?

Я хотел бы найти аналог 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?

3 ответов



(apply '+ (delq nil (mapcar (lambda (x) (and (= 1 (% x 2)) x)) '(1 2 3 4 5))))

идиоматический способ сделать это-использовать функции и макросы в 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))))

но это использует dolist и incf которые оба находятся в cl-macs пакета. В основном вы не можете избежать cl пакет: это


Я согласен с ответ Гарета риса, но если вы используете функциональное программирование и манипулирование данными в своем коде, я настоятельно рекомендуем установить 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)) to --filter мы просто пишем (= (mod it 2) 1), где it используется для локальной переменной.