Что эквивалентно foldr, foldl в Emacs Lisp?
Что эквивалентно foldr, foldl в Emacs Lisp?
Ответ 1
Если вы
(require 'cl)
то вы можете использовать функцию Common Lisp reduce
. Передайте аргумент ключевого слова :from-end t
для foldr
.
ELISP> (reduce #'list '(1 2 3 4))
(((1 2) 3) 4)
ELISP> (reduce #'list '(1 2 3 4) :from-end t)
(1 (2 (3 4)))
Ответ 2
Начиная с Emacs-24.3 мы рекомендуем использовать cl-lib
над cl
(который планируется удалить в каком-то отдаленном будущем), поэтому это будет:
(require 'cl-lib)
(cl-reduce #'list '(1 2 3 4))
а с Emacs-25 вы также можете использовать пакет seq
для этого:
(require 'seq)
(seq-reduce #'list '(1 2 3 4))
Ответ 3
Общая библиотека Lisp предоставляет множество функций последовательности как отображение, фильтрация, свертывание, поиск и даже сортировка. Библиотека CL поставляется с Emacs по умолчанию, поэтому вы должны придерживаться ее. Мне действительно нравится библиотека dash.el
, поскольку она предоставляет огромное количество функций для манипуляций списком и деревом. Он также поддерживает анафорические макросы и поощряет функциональное программирование, что делает код кратким и элегантным.
Складки Haskell соответствуют складкам dash.el
:
-
foldl
с-reduce-from
-
foldr
с-reduce-r-from
-
foldl1
с-reduce
-
foldr1
с-reduce-r
Сумма диапазона от 1 до 10 с использованием складок может выглядеть в этом в Haskell и dash.el
:
foldl (+) 0 [1..10] -- Haskell
(-reduce-from '+ 0 (number-sequence 1 10)) ; Elisp
Вы, наверное, знаете, что складки очень общие, и можно реализовать карты и фильтры с помощью сгибов. Например, чтобы увеличить каждый элемент на 2, каркасы и секции Haskell позволят использовать краткий код, но в Elisp вы обычно пишете многословные выбросы лямбда:
foldr ((:) . (+2)) [] [1..10] -- Haskell
(-reduce-r-from (lambda (x acc) (cons (+ x 2) acc)) '() (number-sequence 1 10)) ; Elisp
Угадайте, что нет необходимости в dash.el
с анафорическими макросами, которые допускают специальный синтаксис, выставляя переменные лямбды как ярлыки, например it
и acc
в складках. Анафорические функции начинаются с 2 тире вместо 1:
(--reduce-r-from (cons (+ it 2) acc) '() (number-sequence 1 10))
В dash.el
есть много функций типа сгиба:
;; Count elements matching a predicate
(-count 'evenp '(1 2 3 4 5)) ; 2
;; Add/multiply elements of a list together
(-sum '(1 2 3 4 5)) ; 15
(-product '(1 2 3 4 5)) ; 120
;; Find the smallest and largest element
(-min '(3 1 -1 2 4)) ; -1
(-max '(-10 0 10 5)) ; 10
;; Find smallest/largest with a custom rule (anaphoric versions)
(--min-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (6)
(--max-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (1 2 3)