Emacs Lisp: Как суммировать нечетные числа в списке? - PullRequest
7 голосов
/ 26 февраля 2009

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

14 голосов
/ 26 февраля 2009

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

Мое лучшее усилие, использующее абсолютно никаких cl средств, таково:

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

но было бы абсурдно использовать это на практике вместо (loop ...) версии.

6 голосов
/ 26 февраля 2009

(apply '+ (delq nil (mapcar (lambda (x) (and (= 1 (% x 2)) x)) '(1 2 3 4 5))))
1 голос
/ 18 марта 2014

Я согласен с ответом Гарета Риса , но если вы используете в своем коде функциональное программирование и манипулирование данными, я настоятельно рекомендую установить dash.el API-интерфейс Magnar Sveen. Он имеет смешное количество функций для написания лаконичного и элегантного функционального кода. Кстати, он сам написан без библиотеки cl. Суммирование нечетных чисел в списке будет:

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

-sum - это сокращение от (-reduce '+ xs). Функции, начинающиеся с двух дефисов: анафорические макросы , они предоставляют временную переменную. Например, здесь вместо передачи (lambda (x) (= (mod x 2) 1)) в --filter мы просто пишем (= (mod it 2) 1), где it используется для локальной переменной.

...