]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
update dash
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Wed, 21 May 2025 11:57:31 +0000 (13:57 +0200)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Wed, 21 May 2025 11:57:31 +0000 (13:57 +0200)
bba.org
elpa/dash-20240510.1327/dash-autoloads.el [deleted file]
elpa/dash-20240510.1327/dash-pkg.el [deleted file]
elpa/dash-20240510.1327/dash.el [deleted file]
elpa/dash-20240510.1327/dash.info [deleted file]
elpa/dash-20240510.1327/dir [deleted file]
elpa/dash-20250312.1307/dash-autoloads.el [new file with mode: 0644]
elpa/dash-20250312.1307/dash-pkg.el [new file with mode: 0644]
elpa/dash-20250312.1307/dash.el [new file with mode: 0644]
elpa/dash-20250312.1307/dash.info [new file with mode: 0644]
elpa/dash-20250312.1307/dir [new file with mode: 0644]

diff --git a/bba.org b/bba.org
index 86d0be7b7dc0ab1a905eb53d18d6682e83007ded..ffec4ae6aa0f40a9422ee4faa218415f600f62e0 100644 (file)
--- a/bba.org
+++ b/bba.org
@@ -389,7 +389,7 @@ Some key bindings taken from [[https://ebzzry.github.io/emacs-pairs.html][emacs-
   (if (>= emacs-major-version 24)
       (progn
         (add-to-list 'load-path "~/.emacs.d/elpa/smartparens-20230529.1017")
-        (add-to-list 'load-path "~/.emacs.d/elpa/dash-20230714.723")
+        (add-to-list 'load-path "~/.emacs.d/elpa/dash-20250312.1307")
         (require 'smartparens)
         (smartparens-global-mode 1)
         (defmacro def-pairs (pairs)
diff --git a/elpa/dash-20240510.1327/dash-autoloads.el b/elpa/dash-20240510.1327/dash-autoloads.el
deleted file mode 100644 (file)
index f908413..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-;;; dash-autoloads.el --- automatically extracted autoloads (do not edit)   -*- lexical-binding: t -*-
-;; Generated by the `loaddefs-generate' function.
-
-;; This file is part of GNU Emacs.
-
-;;; Code:
-
-(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
-
-
-\f
-;;; Generated autoloads from dash.el
-
-(autoload 'dash-fontify-mode "dash" "\
-Toggle fontification of Dash special variables.
-
-Dash-Fontify mode is a buffer-local minor mode intended for Emacs
-Lisp buffers.  Enabling it causes the special variables bound in
-anaphoric Dash macros to be fontified.  These anaphoras include
-`it', `it-index', `acc', and `other'.  In older Emacs versions
-which do not dynamically detect macros, Dash-Fontify mode
-additionally fontifies Dash macro calls.
-
-See also `dash-fontify-mode-lighter' and
-`global-dash-fontify-mode'.
-
-This is a minor mode.  If called interactively, toggle the
-`Dash-Fontify mode' mode.  If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'.  Enable
-the mode if ARG is nil, omitted, or is a positive number.
-Disable the mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `dash-fontify-mode'.
-
-The mode's hook is called both when the mode is enabled and when
-it is disabled.
-
-(fn &optional ARG)" t)
-(put 'global-dash-fontify-mode 'globalized-minor-mode t)
-(defvar global-dash-fontify-mode nil "\
-Non-nil if Global Dash-Fontify mode is enabled.
-See the `global-dash-fontify-mode' command
-for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `global-dash-fontify-mode'.")
-(custom-autoload 'global-dash-fontify-mode "dash" nil)
-(autoload 'global-dash-fontify-mode "dash" "\
-Toggle Dash-Fontify mode in all buffers.
-With prefix ARG, enable Global Dash-Fontify mode if ARG is positive;
-otherwise, disable it.
-
-If called from Lisp, toggle the mode if ARG is `toggle'.
-Enable the mode if ARG is nil, omitted, or is a positive number.
-Disable the mode if ARG is a negative number.
-
-Dash-Fontify mode is enabled in all buffers where
-`dash--turn-on-fontify-mode' would do it.
-
-See `dash-fontify-mode' for more information on Dash-Fontify mode.
-
-(fn &optional ARG)" t)
-(autoload 'dash-register-info-lookup "dash" "\
-Register the Dash Info manual with `info-lookup-symbol'.
-This allows Dash symbols to be looked up with \\[info-lookup-symbol]." t)
-(register-definition-prefixes "dash" '("!cdr" "!cons" "--" "->" "-a" "-butlast" "-c" "-d" "-e" "-f" "-gr" "-i" "-juxt" "-keep" "-l" "-m" "-no" "-o" "-p" "-r" "-s" "-t" "-u" "-value-to-list" "-when-let" "-zip" "dash-"))
-\f
-;;; End of scraped data
-
-(provide 'dash-autoloads)
-
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; no-native-compile: t
-;; coding: utf-8-emacs-unix
-;; End:
-
-;;; dash-autoloads.el ends here
diff --git a/elpa/dash-20240510.1327/dash-pkg.el b/elpa/dash-20240510.1327/dash-pkg.el
deleted file mode 100644 (file)
index 6b4ebef..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-(define-package "dash" "20240510.1327" "A modern list library for Emacs"
-  '((emacs "24"))
-  :commit "1de9dcb83eacfb162b6d9a118a4770b1281bcd84" :authors
-  '(("Magnar Sveen" . "magnarsNOSPAMgmail.com"))
-  :maintainers
-  '(("Magnar Sveen" . "magnarsNOSPAMgmail.com"))
-  :maintainer
-  '("Magnar Sveen" . "magnarsNOSPAMgmail.com")
-  :keywords
-  '("extensions" "lisp")
-  :url "https://github.com/magnars/dash.el")
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
diff --git a/elpa/dash-20240510.1327/dash.el b/elpa/dash-20240510.1327/dash.el
deleted file mode 100644 (file)
index ed2a859..0000000
+++ /dev/null
@@ -1,4136 +0,0 @@
-;;; dash.el --- A modern list library for Emacs  -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
-
-;; Author: Magnar Sveen <magnarsNOSPAMgmail.com>
-;; Version: 2.19.1
-;; Package-Requires: ((emacs "24"))
-;; Keywords: extensions, lisp
-;; Homepage: https://github.com/magnars/dash.el
-
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; A modern list API for Emacs.
-;;
-;; See its overview at https://github.com/magnars/dash.el#functions.
-
-;;; Code:
-
-(eval-when-compile
-  ;; TODO: Emacs 24.3 first introduced `gv', so remove this and all
-  ;; calls to `defsetf' when support for earlier versions is dropped.
-  (unless (fboundp 'gv-define-setter)
-    (require 'cl))
-
-  ;; - 24.3 started complaining about unknown `declare' props.
-  ;; - 25 introduced `pure' and `side-effect-free'.
-  ;; - 30 introduced `important-return-value'.
-  (when (boundp 'defun-declarations-alist)
-    (dolist (prop '(important-return-value pure side-effect-free))
-      (unless (assq prop defun-declarations-alist)
-        (push (list prop #'ignore) defun-declarations-alist)))))
-
-(defgroup dash ()
-  "Customize group for Dash, a modern list library."
-  :group 'extensions
-  :group 'lisp
-  :prefix "dash-")
-
-(defmacro !cons (car cdr)
-  "Destructive: Set CDR to the cons of CAR and CDR."
-  (declare (debug (form symbolp)))
-  `(setq ,cdr (cons ,car ,cdr)))
-
-(defmacro !cdr (list)
-  "Destructive: Set LIST to the cdr of LIST."
-  (declare (debug (symbolp)))
-  `(setq ,list (cdr ,list)))
-
-(defmacro --each (list &rest body)
-  "Evaluate BODY for each element of LIST and return nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating BODY.
-This is the anaphoric counterpart to `-each'."
-  (declare (debug (form body)) (indent 1))
-  (let ((l (make-symbol "list"))
-        (i (make-symbol "i")))
-    `(let ((,l ,list)
-           (,i 0))
-       (while ,l
-         (let ((it (pop ,l)) (it-index ,i))
-           (ignore it it-index)
-           ,@body)
-         (setq ,i (1+ ,i))))))
-
-(defun -each (list fn)
-  "Call FN on each element of LIST.
-Return nil; this function is intended for side effects.
-
-Its anaphoric counterpart is `--each'.
-
-For access to the current element's index in LIST, see
-`-each-indexed'."
-  (declare (indent 1))
-  (ignore (mapc fn list)))
-
-(defalias '--each-indexed '--each)
-
-(defun -each-indexed (list fn)
-  "Call FN on each index and element of LIST.
-For each ITEM at INDEX in LIST, call (funcall FN INDEX ITEM).
-Return nil; this function is intended for side effects.
-
-See also: `-map-indexed'."
-  (declare (indent 1))
-  (--each list (funcall fn it-index it)))
-
-(defmacro --each-while (list pred &rest body)
-  "Evaluate BODY for each item in LIST, while PRED evaluates to non-nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating PRED or BODY.  Once
-an element is reached for which PRED evaluates to nil, no further
-BODY is evaluated.  The return value is always nil.
-This is the anaphoric counterpart to `-each-while'."
-  (declare (debug (form form body)) (indent 2))
-  (let ((l (make-symbol "list"))
-        (i (make-symbol "i"))
-        (elt (make-symbol "elt")))
-    `(let ((,l ,list)
-           (,i 0)
-           ,elt)
-       (while (when ,l
-                (setq ,elt (car-safe ,l))
-                (let ((it ,elt) (it-index ,i))
-                  (ignore it it-index)
-                  ,pred))
-         (let ((it ,elt) (it-index ,i))
-           (ignore it it-index)
-           ,@body)
-         (setq ,i (1+ ,i) ,l (cdr ,l))))))
-
-(defun -each-while (list pred fn)
-  "Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil.
-Once an ITEM is reached for which PRED returns nil, FN is no
-longer called.  Return nil; this function is intended for side
-effects.
-
-Its anaphoric counterpart is `--each-while'."
-  (declare (indent 2))
-  (--each-while list (funcall pred it) (funcall fn it)))
-
-(defmacro --each-r (list &rest body)
-  "Evaluate BODY for each element of LIST in reversed order.
-Each element of LIST in turn, starting at its end, is bound to
-`it' and its index within LIST to `it-index' before evaluating
-BODY.  The return value is always nil.
-This is the anaphoric counterpart to `-each-r'."
-  (declare (debug (form body)) (indent 1))
-  (let ((v (make-symbol "vector"))
-        (i (make-symbol "i")))
-    ;; Implementation note: building a vector is considerably faster
-    ;; than building a reversed list (vector takes less memory, so
-    ;; there is less GC), plus `length' comes naturally.  In-place
-    ;; `nreverse' would be faster still, but BODY would be able to see
-    ;; that, even if the modification was undone before we return.
-    `(let* ((,v (vconcat ,list))
-            (,i (length ,v))
-            it it-index)
-       (ignore it it-index)
-       (while (> ,i 0)
-         (setq ,i (1- ,i) it-index ,i it (aref ,v ,i))
-         ,@body))))
-
-(defun -each-r (list fn)
-  "Call FN on each element of LIST in reversed order.
-Return nil; this function is intended for side effects.
-
-Its anaphoric counterpart is `--each-r'."
-  (--each-r list (funcall fn it)))
-
-(defmacro --each-r-while (list pred &rest body)
-  "Eval BODY for each item in reversed LIST, while PRED evals to non-nil.
-Each element of LIST in turn, starting at its end, is bound to
-`it' and its index within LIST to `it-index' before evaluating
-PRED or BODY.  Once an element is reached for which PRED
-evaluates to nil, no further BODY is evaluated.  The return value
-is always nil.
-This is the anaphoric counterpart to `-each-r-while'."
-  (declare (debug (form form body)) (indent 2))
-  (let ((v (make-symbol "vector"))
-        (i (make-symbol "i"))
-        (elt (make-symbol "elt")))
-    `(let* ((,v (vconcat ,list))
-            (,i (length ,v))
-            ,elt it it-index)
-       (ignore it it-index)
-       (while (when (> ,i 0)
-                (setq ,i (1- ,i) it-index ,i)
-                (setq ,elt (aref ,v ,i) it ,elt)
-                ,pred)
-         (setq it-index ,i it ,elt)
-         ,@body))))
-
-(defun -each-r-while (list pred fn)
-  "Call FN on each ITEM in reversed LIST, while (PRED ITEM) is non-nil.
-Once an ITEM is reached for which PRED returns nil, FN is no
-longer called.  Return nil; this function is intended for side
-effects.
-
-Its anaphoric counterpart is `--each-r-while'."
-  (--each-r-while list (funcall pred it) (funcall fn it)))
-
-(defmacro --dotimes (num &rest body)
-  "Evaluate BODY NUM times, presumably for side effects.
-BODY is evaluated with the local variable `it' temporarily bound
-to successive integers running from 0, inclusive, to NUM,
-exclusive.  BODY is not evaluated if NUM is less than 1.
-This is the anaphoric counterpart to `-dotimes'."
-  (declare (debug (form body)) (indent 1))
-  (let ((n (make-symbol "num"))
-        (i (make-symbol "i")))
-    `(let ((,n ,num)
-           (,i 0)
-           it)
-       (ignore it)
-       (while (< ,i ,n)
-         (setq it ,i ,i (1+ ,i))
-         ,@body))))
-
-(defun -dotimes (num fn)
-  "Call FN NUM times, presumably for side effects.
-FN is called with a single argument on successive integers
-running from 0, inclusive, to NUM, exclusive.  FN is not called
-if NUM is less than 1.
-
-This function's anaphoric counterpart is `--dotimes'."
-  (declare (indent 1))
-  (--dotimes num (funcall fn it)))
-
-(defun -map (fn list)
-  "Apply FN to each item in LIST and return the list of results.
-
-This function's anaphoric counterpart is `--map'."
-  (declare (important-return-value t))
-  (mapcar fn list))
-
-(defmacro --map (form list)
-  "Eval FORM for each item in LIST and return the list of results.
-Each element of LIST in turn is bound to `it' before evaluating
-FORM.
-This is the anaphoric counterpart to `-map'."
-  (declare (debug (def-form form)))
-  `(mapcar (lambda (it) (ignore it) ,form) ,list))
-
-(defmacro --reduce-from (form init list)
-  "Accumulate a value by evaluating FORM across LIST.
-This macro is like `--each' (which see), but it additionally
-provides an accumulator variable `acc' which it successively
-binds to the result of evaluating FORM for the current LIST
-element before processing the next element.  For the first
-element, `acc' is initialized with the result of evaluating INIT.
-The return value is the resulting value of `acc'.  If LIST is
-empty, FORM is not evaluated, and the return value is the result
-of INIT.
-This is the anaphoric counterpart to `-reduce-from'."
-  (declare (debug (form form form)))
-  `(let ((acc ,init))
-     (--each ,list (setq acc ,form))
-     acc))
-
-(defun -reduce-from (fn init list)
-  "Reduce the function FN across LIST, starting with INIT.
-Return the result of applying FN to INIT and the first element of
-LIST, then applying FN to that result and the second element,
-etc.  If LIST is empty, return INIT without calling FN.
-
-This function's anaphoric counterpart is `--reduce-from'.
-
-For other folds, see also `-reduce' and `-reduce-r'."
-  (declare (important-return-value t))
-  (--reduce-from (funcall fn acc it) init list))
-
-(defmacro --reduce (form list)
-  "Accumulate a value by evaluating FORM across LIST.
-This macro is like `--reduce-from' (which see), except the first
-element of LIST is taken as INIT.  Thus if LIST contains a single
-item, it is returned without evaluating FORM.  If LIST is empty,
-FORM is evaluated with `it' and `acc' bound to nil.
-This is the anaphoric counterpart to `-reduce'."
-  (declare (debug (form form)))
-  (let ((lv (make-symbol "list-value")))
-    `(let ((,lv ,list))
-       (if ,lv
-           (--reduce-from ,form (car ,lv) (cdr ,lv))
-         ;; Explicit nil binding pacifies lexical "variable left uninitialized"
-         ;; warning.  See issue #377 and upstream https://bugs.gnu.org/47080.
-         (let ((acc nil) (it nil))
-           (ignore acc it)
-           ,form)))))
-
-(defun -reduce (fn list)
-  "Reduce the function FN across LIST.
-Return the result of applying FN to the first two elements of
-LIST, then applying FN to that result and the third element, etc.
-If LIST contains a single element, return it without calling FN.
-If LIST is empty, return the result of calling FN with no
-arguments.
-
-This function's anaphoric counterpart is `--reduce'.
-
-For other folds, see also `-reduce-from' and `-reduce-r'."
-  (declare (important-return-value t))
-  (if list
-      (-reduce-from fn (car list) (cdr list))
-    (funcall fn)))
-
-(defmacro --reduce-r-from (form init list)
-  "Accumulate a value by evaluating FORM across LIST in reverse.
-This macro is like `--reduce-from', except it starts from the end
-of LIST.
-This is the anaphoric counterpart to `-reduce-r-from'."
-  (declare (debug (form form form)))
-  `(let ((acc ,init))
-     (--each-r ,list (setq acc ,form))
-     acc))
-
-(defun -reduce-r-from (fn init list)
-  "Reduce the function FN across LIST in reverse, starting with INIT.
-Return the result of applying FN to the last element of LIST and
-INIT, then applying FN to the second-to-last element and the
-previous result of FN, etc.  That is, the first argument of FN is
-the current element, and its second argument the accumulated
-value.  If LIST is empty, return INIT without calling FN.
-
-This function is like `-reduce-from' but the operation associates
-from the right rather than left.  In other words, it starts from
-the end of LIST and flips the arguments to FN.  Conceptually, it
-is like replacing the conses in LIST with applications of FN, and
-its last link with INIT, and evaluating the resulting expression.
-
-This function's anaphoric counterpart is `--reduce-r-from'.
-
-For other folds, see also `-reduce-r' and `-reduce'."
-  (declare (important-return-value t))
-  (--reduce-r-from (funcall fn it acc) init list))
-
-(defmacro --reduce-r (form list)
-  "Accumulate a value by evaluating FORM across LIST in reverse order.
-This macro is like `--reduce', except it starts from the end of
-LIST.
-This is the anaphoric counterpart to `-reduce-r'."
-  (declare (debug (form form)))
-  `(--reduce ,form (reverse ,list)))
-
-(defun -reduce-r (fn list)
-  "Reduce the function FN across LIST in reverse.
-Return the result of applying FN to the last two elements of
-LIST, then applying FN to the third-to-last element and the
-previous result of FN, etc.  That is, the first argument of FN is
-the current element, and its second argument the accumulated
-value.  If LIST contains a single element, return it without
-calling FN.  If LIST is empty, return the result of calling FN
-with no arguments.
-
-This function is like `-reduce' but the operation associates from
-the right rather than left.  In other words, it starts from the
-end of LIST and flips the arguments to FN.  Conceptually, it is
-like replacing the conses in LIST with applications of FN,
-ignoring its last link, and evaluating the resulting expression.
-
-This function's anaphoric counterpart is `--reduce-r'.
-
-For other folds, see also `-reduce-r-from' and `-reduce'."
-  (declare (important-return-value t))
-  (if list
-      (--reduce-r (funcall fn it acc) list)
-    (funcall fn)))
-
-(defmacro --reductions-from (form init list)
-  "Return a list of FORM's intermediate reductions across LIST.
-That is, a list of the intermediate values of the accumulator
-when `--reduce-from' (which see) is called with the same
-arguments.
-This is the anaphoric counterpart to `-reductions-from'."
-  (declare (debug (form form form)))
-  `(nreverse
-    (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
-                   (list ,init)
-                   ,list)))
-
-(defun -reductions-from (fn init list)
-  "Return a list of FN's intermediate reductions across LIST.
-That is, a list of the intermediate values of the accumulator
-when `-reduce-from' (which see) is called with the same
-arguments.
-
-This function's anaphoric counterpart is `--reductions-from'.
-
-For other folds, see also `-reductions' and `-reductions-r'."
-  (declare (important-return-value t))
-  (--reductions-from (funcall fn acc it) init list))
-
-(defmacro --reductions (form list)
-  "Return a list of FORM's intermediate reductions across LIST.
-That is, a list of the intermediate values of the accumulator
-when `--reduce' (which see) is called with the same arguments.
-This is the anaphoric counterpart to `-reductions'."
-  (declare (debug (form form)))
-  (let ((lv (make-symbol "list-value")))
-    `(let ((,lv ,list))
-       (if ,lv
-           (--reductions-from ,form (car ,lv) (cdr ,lv))
-         ;; Explicit nil binding pacifies lexical "variable left uninitialized"
-         ;; warning.  See issue #377 and upstream https://bugs.gnu.org/47080.
-         (let ((acc nil) (it nil))
-           (ignore acc it)
-           (list ,form))))))
-
-(defun -reductions (fn list)
-  "Return a list of FN's intermediate reductions across LIST.
-That is, a list of the intermediate values of the accumulator
-when `-reduce' (which see) is called with the same arguments.
-
-This function's anaphoric counterpart is `--reductions'.
-
-For other folds, see also `-reductions' and `-reductions-r'."
-  (declare (important-return-value t))
-  (if list
-      (--reductions-from (funcall fn acc it) (car list) (cdr list))
-    (list (funcall fn))))
-
-(defmacro --reductions-r-from (form init list)
-  "Return a list of FORM's intermediate reductions across reversed LIST.
-That is, a list of the intermediate values of the accumulator
-when `--reduce-r-from' (which see) is called with the same
-arguments.
-This is the anaphoric counterpart to `-reductions-r-from'."
-  (declare (debug (form form form)))
-  `(--reduce-r-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
-                    (list ,init)
-                    ,list))
-
-(defun -reductions-r-from (fn init list)
-  "Return a list of FN's intermediate reductions across reversed LIST.
-That is, a list of the intermediate values of the accumulator
-when `-reduce-r-from' (which see) is called with the same
-arguments.
-
-This function's anaphoric counterpart is `--reductions-r-from'.
-
-For other folds, see also `-reductions' and `-reductions-r'."
-  (declare (important-return-value t))
-  (--reductions-r-from (funcall fn it acc) init list))
-
-(defmacro --reductions-r (form list)
-  "Return a list of FORM's intermediate reductions across reversed LIST.
-That is, a list of the intermediate values of the accumulator
-when `--reduce-re' (which see) is called with the same arguments.
-This is the anaphoric counterpart to `-reductions-r'."
-  (declare (debug (form list)))
-  (let ((lv (make-symbol "list-value")))
-    `(let ((,lv (reverse ,list)))
-       (if ,lv
-           (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
-                          (list (car ,lv))
-                          (cdr ,lv))
-         ;; Explicit nil binding pacifies lexical "variable left uninitialized"
-         ;; warning.  See issue #377 and upstream https://bugs.gnu.org/47080.
-         (let ((acc nil) (it nil))
-           (ignore acc it)
-           (list ,form))))))
-
-(defun -reductions-r (fn list)
-  "Return a list of FN's intermediate reductions across reversed LIST.
-That is, a list of the intermediate values of the accumulator
-when `-reduce-r' (which see) is called with the same arguments.
-
-This function's anaphoric counterpart is `--reductions-r'.
-
-For other folds, see also `-reductions-r-from' and
-`-reductions'."
-  (declare (important-return-value t))
-  (if list
-      (--reductions-r (funcall fn it acc) list)
-    (list (funcall fn))))
-
-(defmacro --filter (form list)
-  "Return a new list of the items in LIST for which FORM evals to non-nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-filter'.
-For the opposite operation, see also `--remove'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result")))
-    `(let (,r)
-       (--each ,list (when ,form (push it ,r)))
-       (nreverse ,r))))
-
-(defun -filter (pred list)
-  "Return a new list of the items in LIST for which PRED returns non-nil.
-
-Alias: `-select'.
-
-This function's anaphoric counterpart is `--filter'.
-
-For similar operations, see also `-keep' and `-remove'."
-  (declare (important-return-value t))
-  (--filter (funcall pred it) list))
-
-(defalias '-select '-filter)
-(defalias '--select '--filter)
-
-(defmacro --remove (form list)
-  "Return a new list of the items in LIST for which FORM evals to nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-remove'.
-For the opposite operation, see also `--filter'."
-  (declare (debug (form form)))
-  `(--filter (not ,form) ,list))
-
-(defun -remove (pred list)
-  "Return a new list of the items in LIST for which PRED returns nil.
-
-Alias: `-reject'.
-
-This function's anaphoric counterpart is `--remove'.
-
-For similar operations, see also `-keep' and `-filter'."
-  (declare (important-return-value t))
-  (--remove (funcall pred it) list))
-
-(defalias '-reject '-remove)
-(defalias '--reject '--remove)
-
-(defmacro --remove-first (form list)
-  "Remove the first item from LIST for which FORM evals to non-nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.  This is a
-non-destructive operation, but only the front of LIST leading up
-to the removed item is a copy; the rest is LIST's original tail.
-If no item is removed, then the result is a complete copy.
-This is the anaphoric counterpart to `-remove-first'."
-  (declare (debug (form form)))
-  (let ((front (make-symbol "front"))
-        (tail (make-symbol "tail")))
-    `(let ((,tail ,list) ,front)
-       (--each-while ,tail (not ,form)
-         (push (pop ,tail) ,front))
-       (if ,tail
-           (nconc (nreverse ,front) (cdr ,tail))
-         (nreverse ,front)))))
-
-(defun -remove-first (pred list)
-  "Remove the first item from LIST for which PRED returns non-nil.
-This is a non-destructive operation, but only the front of LIST
-leading up to the removed item is a copy; the rest is LIST's
-original tail.  If no item is removed, then the result is a
-complete copy.
-
-Alias: `-reject-first'.
-
-This function's anaphoric counterpart is `--remove-first'.
-
-See also `-map-first', `-remove-item', and `-remove-last'."
-  (declare (important-return-value t))
-  (--remove-first (funcall pred it) list))
-
-;; TODO: #'-quoting the macro upsets Emacs 24.
-(defalias '-reject-first #'-remove-first)
-(defalias '--reject-first '--remove-first)
-
-(defmacro --remove-last (form list)
-  "Remove the last item from LIST for which FORM evals to non-nil.
-Each element of LIST in turn is bound to `it' before evaluating
-FORM.  The result is a copy of LIST regardless of whether an
-element is removed.
-This is the anaphoric counterpart to `-remove-last'."
-  (declare (debug (form form)))
-  `(nreverse (--remove-first ,form (reverse ,list))))
-
-(defun -remove-last (pred list)
-  "Remove the last item from LIST for which PRED returns non-nil.
-The result is a copy of LIST regardless of whether an element is
-removed.
-
-Alias: `-reject-last'.
-
-This function's anaphoric counterpart is `--remove-last'.
-
-See also `-map-last', `-remove-item', and `-remove-first'."
-  (declare (important-return-value t))
-  (--remove-last (funcall pred it) list))
-
-(defalias '-reject-last '-remove-last)
-(defalias '--reject-last '--remove-last)
-
-(defalias '-remove-item #'remove
-  "Return a copy of LIST with all occurrences of ITEM removed.
-The comparison is done with `equal'.
-\n(fn ITEM LIST)")
-
-(defmacro --keep (form list)
-  "Eval FORM for each item in LIST and return the non-nil results.
-Like `--filter', but returns the non-nil results of FORM instead
-of the corresponding elements of LIST.  Each element of LIST in
-turn is bound to `it' and its index within LIST to `it-index'
-before evaluating FORM.
-This is the anaphoric counterpart to `-keep'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result"))
-        (m (make-symbol "mapped")))
-    `(let (,r)
-       (--each ,list (let ((,m ,form)) (when ,m (push ,m ,r))))
-       (nreverse ,r))))
-
-(defun -keep (fn list)
-  "Return a new list of the non-nil results of applying FN to each item in LIST.
-Like `-filter', but returns the non-nil results of FN instead of
-the corresponding elements of LIST.
-
-Its anaphoric counterpart is `--keep'."
-  (declare (important-return-value t))
-  (--keep (funcall fn it) list))
-
-(defun -non-nil (list)
-  "Return a copy of LIST with all nil items removed."
-  (declare (side-effect-free t))
-  (--filter it list))
-
-(defmacro --map-indexed (form list)
-  "Eval FORM for each item in LIST and return the list of results.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.  This is like
-`--map', but additionally makes `it-index' available to FORM.
-
-This is the anaphoric counterpart to `-map-indexed'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result")))
-    `(let (,r)
-       (--each ,list
-         (push ,form ,r))
-       (nreverse ,r))))
-
-(defun -map-indexed (fn list)
-  "Apply FN to each index and item in LIST and return the list of results.
-This is like `-map', but FN takes two arguments: the index of the
-current element within LIST, and the element itself.
-
-This function's anaphoric counterpart is `--map-indexed'.
-
-For a side-effecting variant, see also `-each-indexed'."
-  (declare (important-return-value t))
-  (--map-indexed (funcall fn it-index it) list))
-
-(defmacro --map-when (pred rep list)
-  "Anaphoric form of `-map-when'."
-  (declare (debug (form form form)))
-  (let ((r (make-symbol "result")))
-    `(let (,r)
-       (--each ,list (!cons (if ,pred ,rep it) ,r))
-       (nreverse ,r))))
-
-(defun -map-when (pred rep list)
-  "Use PRED to conditionally apply REP to each item in LIST.
-Return a copy of LIST where the items for which PRED returns nil
-are unchanged, and the rest are mapped through the REP function.
-
-Alias: `-replace-where'
-
-See also: `-update-at'"
-  (declare (important-return-value t))
-  (--map-when (funcall pred it) (funcall rep it) list))
-
-(defalias '-replace-where '-map-when)
-(defalias '--replace-where '--map-when)
-
-(defun -map-first (pred rep list)
-  "Use PRED to determine the first item in LIST to call REP on.
-Return a copy of LIST where the first item for which PRED returns
-non-nil is replaced with the result of calling REP on that item.
-
-See also: `-map-when', `-replace-first'"
-  (declare (important-return-value t))
-  (let (front)
-    (while (and list (not (funcall pred (car list))))
-      (push (car list) front)
-      (!cdr list))
-    (if list
-        (-concat (nreverse front) (cons (funcall rep (car list)) (cdr list)))
-      (nreverse front))))
-
-(defmacro --map-first (pred rep list)
-  "Anaphoric form of `-map-first'."
-  (declare (debug (def-form def-form form)))
-  `(-map-first (lambda (it) (ignore it) ,pred)
-               (lambda (it) (ignore it) ,rep)
-               ,list))
-
-(defun -map-last (pred rep list)
-  "Use PRED to determine the last item in LIST to call REP on.
-Return a copy of LIST where the last item for which PRED returns
-non-nil is replaced with the result of calling REP on that item.
-
-See also: `-map-when', `-replace-last'"
-  (declare (important-return-value t))
-  (nreverse (-map-first pred rep (reverse list))))
-
-(defmacro --map-last (pred rep list)
-  "Anaphoric form of `-map-last'."
-  (declare (debug (def-form def-form form)))
-  `(-map-last (lambda (it) (ignore it) ,pred)
-              (lambda (it) (ignore it) ,rep)
-              ,list))
-
-(defun -replace (old new list)
-  "Replace all OLD items in LIST with NEW.
-
-Elements are compared using `equal'.
-
-See also: `-replace-at'"
-  (declare (pure t) (side-effect-free t))
-  (--map-when (equal it old) new list))
-
-(defun -replace-first (old new list)
-  "Replace the first occurrence of OLD with NEW in LIST.
-
-Elements are compared using `equal'.
-
-See also: `-map-first'"
-  (declare (pure t) (side-effect-free t))
-  (--map-first (equal old it) new list))
-
-(defun -replace-last (old new list)
-  "Replace the last occurrence of OLD with NEW in LIST.
-
-Elements are compared using `equal'.
-
-See also: `-map-last'"
-  (declare (pure t) (side-effect-free t))
-  (--map-last (equal old it) new list))
-
-(defmacro --mapcat (form list)
-  "Anaphoric form of `-mapcat'."
-  (declare (debug (form form)))
-  `(apply #'append (--map ,form ,list)))
-
-(defun -mapcat (fn list)
-  "Return the concatenation of the result of mapping FN over LIST.
-Thus function FN should return a list."
-  (declare (important-return-value t))
-  (--mapcat (funcall fn it) list))
-
-(defmacro --iterate (form init n)
-  "Anaphoric version of `-iterate'."
-  (declare (debug (form form form)))
-  (let ((res (make-symbol "result"))
-        (len (make-symbol "n")))
-    `(let ((,len ,n))
-       (when (> ,len 0)
-         (let* ((it ,init)
-                (,res (list it)))
-           (dotimes (_ (1- ,len))
-             (push (setq it ,form) ,res))
-           (nreverse ,res))))))
-
-(defun -iterate (fun init n)
-  "Return a list of iterated applications of FUN to INIT.
-
-This means a list of the form:
-
-  (INIT (FUN INIT) (FUN (FUN INIT)) ...)
-
-N is the length of the returned list."
-  (declare (important-return-value t))
-  (--iterate (funcall fun it) init n))
-
-(defun -flatten (l)
-  "Take a nested list L and return its contents as a single, flat list.
-
-Note that because nil represents a list of zero elements (an
-empty list), any mention of nil in L will disappear after
-flattening.  If you need to preserve nils, consider `-flatten-n'
-or map them to some unique symbol and then map them back.
-
-Conses of two atoms are considered \"terminals\", that is, they
-aren't flattened further.
-
-See also: `-flatten-n'"
-  (declare (pure t) (side-effect-free t))
-  (if (and (listp l) (listp (cdr l)))
-      (-mapcat '-flatten l)
-    (list l)))
-
-(defun -flatten-n (num list)
-  "Flatten NUM levels of a nested LIST.
-
-See also: `-flatten'"
-  (declare (pure t) (side-effect-free t))
-  (dotimes (_ num)
-    (setq list (apply #'append (mapcar #'-list list))))
-  list)
-
-(defalias '-concat #'append
-  "Concatenate all the arguments and make the result a list.
-The result is a list whose elements are the elements of all the arguments.
-Each argument may be a list, vector or string.
-
-All arguments except the last argument are copied.  The last argument
-is just used as the tail of the new list.
-
-\(fn &rest SEQUENCES)")
-
-(defalias '-copy #'copy-sequence
-  "Create a shallow copy of LIST.
-
-\(fn LIST)")
-
-(defmacro --splice (pred form list)
-  "Splice lists generated by FORM in place of items satisfying PRED in LIST.
-
-Evaluate PRED for each element of LIST in turn bound to `it'.
-Whenever the result of PRED is nil, leave that `it' is-is.
-Otherwise, evaluate FORM with the same `it' binding still in
-place.  The result should be a (possibly empty) list of items to
-splice in place of `it' in LIST.
-
-This can be useful as an alternative to the `,@' construct in a
-`\\=`' structure, in case you need to splice several lists at
-marked positions (for example with keywords).
-
-This is the anaphoric counterpart to `-splice'."
-  (declare (debug (form form form)))
-  (let ((r (make-symbol "result")))
-    `(let (,r)
-       (--each ,list
-         (if ,pred
-             (--each ,form (push it ,r))
-           (push it ,r)))
-       (nreverse ,r))))
-
-(defun -splice (pred fun list)
-  "Splice lists generated by FUN in place of items satisfying PRED in LIST.
-
-Call PRED on each element of LIST.  Whenever the result of PRED
-is nil, leave that `it' as-is.  Otherwise, call FUN on the same
-`it' that satisfied PRED.  The result should be a (possibly
-empty) list of items to splice in place of `it' in LIST.
-
-This can be useful as an alternative to the `,@' construct in a
-`\\=`' structure, in case you need to splice several lists at
-marked positions (for example with keywords).
-
-This function's anaphoric counterpart is `--splice'.
-
-See also: `-splice-list', `-insert-at'."
-  (declare (important-return-value t))
-  (--splice (funcall pred it) (funcall fun it) list))
-
-(defun -splice-list (pred new-list list)
-  "Splice NEW-LIST in place of elements matching PRED in LIST.
-
-See also: `-splice', `-insert-at'"
-  (declare (important-return-value t))
-  (-splice pred (lambda (_) new-list) list))
-
-(defmacro --splice-list (pred new-list list)
-  "Anaphoric form of `-splice-list'."
-  (declare (debug (def-form form form)))
-  `(-splice-list (lambda (it) (ignore it) ,pred) ,new-list ,list))
-
-(defun -cons* (&rest args)
-  "Make a new list from the elements of ARGS.
-The last 2 elements of ARGS are used as the final cons of the
-result, so if the final element of ARGS is not a list, the result
-is a dotted list.  With no ARGS, return nil."
-  (declare (side-effect-free t))
-  (let* ((len (length args))
-         (tail (nthcdr (- len 2) args))
-         (last (cdr tail)))
-    (if (null last)
-        (car args)
-      (setcdr tail (car last))
-      args)))
-
-(defun -snoc (list elem &rest elements)
-  "Append ELEM to the end of the list.
-
-This is like `cons', but operates on the end of list.
-
-If any ELEMENTS are given, append them to the list as well."
-  (declare (side-effect-free t))
-  (-concat list (list elem) elements))
-
-(defmacro --first (form list)
-  "Return the first item in LIST for which FORM evals to non-nil.
-Return nil if no such element is found.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-first'."
-  (declare (debug (form form)))
-  (let ((n (make-symbol "needle")))
-    `(let (,n)
-       (--each-while ,list (or (not ,form)
-                               (ignore (setq ,n it))))
-       ,n)))
-
-(defun -first (pred list)
-  "Return the first item in LIST for which PRED returns non-nil.
-Return nil if no such element is found.
-
-To get the first item in the list no questions asked,
-use `-first-item'.
-
-Alias: `-find'.
-
-This function's anaphoric counterpart is `--first'."
-  (declare (important-return-value t))
-  (--first (funcall pred it) list))
-
-(defalias '-find #'-first)
-(defalias '--find '--first)
-
-(defmacro --some (form list)
-  "Return non-nil if FORM evals to non-nil for at least one item in LIST.
-If so, return the first such result of FORM.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-some'."
-  (declare (debug (form form)))
-  (let ((n (make-symbol "needle")))
-    `(let (,n)
-       (--each-while ,list (not (setq ,n ,form)))
-       ,n)))
-
-(defun -some (pred list)
-  "Return (PRED x) for the first LIST item where (PRED x) is non-nil, else nil.
-
-Alias: `-any'.
-
-This function's anaphoric counterpart is `--some'."
-  (declare (important-return-value t))
-  (--some (funcall pred it) list))
-
-(defalias '-any '-some)
-(defalias '--any '--some)
-
-(defmacro --every (form list)
-  "Return non-nil if FORM evals to non-nil for all items in LIST.
-If so, return the last such result of FORM.  Otherwise, once an
-item is reached for which FORM yields nil, return nil without
-evaluating FORM for any further LIST elements.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-
-This macro is like `--every-p', but on success returns the last
-non-nil result of FORM instead of just t.
-
-This is the anaphoric counterpart to `-every'."
-  (declare (debug (form form)))
-  (let ((a (make-symbol "all")))
-    `(let ((,a t))
-       (--each-while ,list (setq ,a ,form))
-       ,a)))
-
-(defun -every (pred list)
-  "Return non-nil if PRED returns non-nil for all items in LIST.
-If so, return the last such result of PRED.  Otherwise, once an
-item is reached for which PRED returns nil, return nil without
-calling PRED on any further LIST elements.
-
-This function is like `-every-p', but on success returns the last
-non-nil result of PRED instead of just t.
-
-This function's anaphoric counterpart is `--every'."
-  (declare (important-return-value t))
-  (--every (funcall pred it) list))
-
-(defmacro --last (form list)
-  "Anaphoric form of `-last'."
-  (declare (debug (form form)))
-  (let ((n (make-symbol "needle")))
-    `(let (,n)
-       (--each ,list
-         (when ,form (setq ,n it)))
-       ,n)))
-
-(defun -last (pred list)
-  "Return the last x in LIST where (PRED x) is non-nil, else nil."
-  (declare (important-return-value t))
-  (--last (funcall pred it) list))
-
-(defalias '-first-item #'car
-  "Return the first item of LIST, or nil on an empty list.
-
-See also: `-second-item', `-last-item', etc.
-
-\(fn LIST)")
-
-;; Ensure that calls to `-first-item' are compiled to a single opcode,
-;; just like `car'.
-(put '-first-item 'byte-opcode 'byte-car)
-(put '-first-item 'byte-compile 'byte-compile-one-arg)
-(put '-first-item 'pure t)
-(put '-first-item 'side-effect-free t)
-
-(defalias '-second-item #'cadr
-  "Return the second item of LIST, or nil if LIST is too short.
-
-See also: `-first-item', `-third-item', etc.
-
-\(fn LIST)")
-
-(put '-second-item 'pure t)
-(put '-second-item 'side-effect-free t)
-
-(defalias '-third-item
-  (if (fboundp 'caddr)
-      #'caddr
-    (lambda (list) (car (cddr list))))
-  "Return the third item of LIST, or nil if LIST is too short.
-
-See also: `-second-item', `-fourth-item', etc.
-
-\(fn LIST)")
-
-(put '-third-item 'pure t)
-(put '-third-item 'side-effect-free t)
-
-(defalias '-fourth-item
-  (if (fboundp 'cadddr)
-      #'cadddr
-    (lambda (list) (cadr (cddr list))))
-  "Return the fourth item of LIST, or nil if LIST is too short.
-
-See also: `-third-item', `-fifth-item', etc.
-
-\(fn LIST)")
-
-(put '-fourth-item 'pure t)
-(put '-fourth-item 'side-effect-free t)
-
-(defun -fifth-item (list)
-  "Return the fifth item of LIST, or nil if LIST is too short.
-
-See also: `-fourth-item', `-last-item', etc."
-  (declare (pure t) (side-effect-free t))
-  (car (cddr (cddr list))))
-
-(defun -last-item (list)
-  "Return the last item of LIST, or nil on an empty list.
-
-See also: `-first-item', etc."
-  (declare (pure t) (side-effect-free t))
-  (car (last list)))
-
-;; Use `with-no-warnings' to suppress unbound `-last-item' or
-;; undefined `gv--defsetter' warnings arising from both
-;; `gv-define-setter' and `defsetf' in certain Emacs versions.
-(with-no-warnings
-  (if (fboundp 'gv-define-setter)
-      (gv-define-setter -last-item (val x) `(setcar (last ,x) ,val))
-    (defsetf -last-item (x) (val) `(setcar (last ,x) ,val))))
-
-(defun -butlast (list)
-  "Return a list of all items in list except for the last."
-  ;; no alias as we don't want magic optional argument
-  (declare (pure t) (side-effect-free t))
-  (butlast list))
-
-(defmacro --count (pred list)
-  "Anaphoric form of `-count'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result")))
-    `(let ((,r 0))
-       (--each ,list (when ,pred (setq ,r (1+ ,r))))
-       ,r)))
-
-(defun -count (pred list)
-  "Counts the number of items in LIST where (PRED item) is non-nil."
-  (declare (important-return-value t))
-  (--count (funcall pred it) list))
-
-(defun ---truthy? (obj)
-  "Return OBJ as a boolean value (t or nil)."
-  (declare (pure t) (side-effect-free error-free))
-  (and obj t))
-
-(defmacro --any? (form list)
-  "Anaphoric form of `-any?'."
-  (declare (debug (form form)))
-  `(and (--some ,form ,list) t))
-
-(defun -any? (pred list)
-  "Return t if (PRED X) is non-nil for any X in LIST, else nil.
-
-Alias: `-any-p', `-some?', `-some-p'"
-  (declare (important-return-value t))
-  (--any? (funcall pred it) list))
-
-(defalias '-some? '-any?)
-(defalias '--some? '--any?)
-(defalias '-any-p '-any?)
-(defalias '--any-p '--any?)
-(defalias '-some-p '-any?)
-(defalias '--some-p '--any?)
-
-(defmacro --all? (form list)
-  "Return t if FORM evals to non-nil for all items in LIST.
-Otherwise, once an item is reached for which FORM yields nil,
-return nil without evaluating FORM for any further LIST elements.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-
-The similar macro `--every' is more widely useful, since it
-returns the last non-nil result of FORM instead of just t on
-success.
-
-Alias: `--all-p', `--every-p', `--every?'.
-
-This is the anaphoric counterpart to `-all?'."
-  (declare (debug (form form)))
-  `(and (--every ,form ,list) t))
-
-(defun -all? (pred list)
-  "Return t if (PRED X) is non-nil for all X in LIST, else nil.
-In the latter case, stop after the first X for which (PRED X) is
-nil, without calling PRED on any subsequent elements of LIST.
-
-The similar function `-every' is more widely useful, since it
-returns the last non-nil result of PRED instead of just t on
-success.
-
-Alias: `-all-p', `-every-p', `-every?'.
-
-This function's anaphoric counterpart is `--all?'."
-  (declare (important-return-value t))
-  (--all? (funcall pred it) list))
-
-(defalias '-every? '-all?)
-(defalias '--every? '--all?)
-(defalias '-all-p '-all?)
-(defalias '--all-p '--all?)
-(defalias '-every-p '-all?)
-(defalias '--every-p '--all?)
-
-(defmacro --none? (form list)
-  "Anaphoric form of `-none?'."
-  (declare (debug (form form)))
-  `(--all? (not ,form) ,list))
-
-(defun -none? (pred list)
-  "Return t if (PRED X) is nil for all X in LIST, else nil.
-
-Alias: `-none-p'"
-  (declare (important-return-value t))
-  (--none? (funcall pred it) list))
-
-(defalias '-none-p '-none?)
-(defalias '--none-p '--none?)
-
-(defmacro --only-some? (form list)
-  "Anaphoric form of `-only-some?'."
-  (declare (debug (form form)))
-  (let ((y (make-symbol "yes"))
-        (n (make-symbol "no")))
-    `(let (,y ,n)
-       (--each-while ,list (not (and ,y ,n))
-         (if ,form (setq ,y t) (setq ,n t)))
-       (---truthy? (and ,y ,n)))))
-
-(defun -only-some? (pred list)
-  "Return t if different LIST items both satisfy and do not satisfy PRED.
-That is, if PRED returns both nil for at least one item, and
-non-nil for at least one other item in LIST.  Return nil if all
-items satisfy the predicate or none of them do.
-
-Alias: `-only-some-p'"
-  (declare (important-return-value t))
-  (--only-some? (funcall pred it) list))
-
-(defalias '-only-some-p '-only-some?)
-(defalias '--only-some-p '--only-some?)
-
-(defun -slice (list from &optional to step)
-  "Return copy of LIST, starting from index FROM to index TO.
-
-FROM or TO may be negative.  These values are then interpreted
-modulo the length of the list.
-
-If STEP is a number, only each STEPth item in the resulting
-section is returned.  Defaults to 1."
-  (declare (side-effect-free t))
-  (let ((length (length list))
-        (new-list nil))
-    ;; to defaults to the end of the list
-    (setq to (or to length))
-    (setq step (or step 1))
-    ;; handle negative indices
-    (when (< from 0)
-      (setq from (mod from length)))
-    (when (< to 0)
-      (setq to (mod to length)))
-
-    ;; iterate through the list, keeping the elements we want
-    (--each-while list (< it-index to)
-      (when (and (>= it-index from)
-                 (= (mod (- from it-index) step) 0))
-        (push it new-list)))
-    (nreverse new-list)))
-
-(defmacro --take-while (form list)
-  "Take successive items from LIST for which FORM evals to non-nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.  Return a new
-list of the successive elements from the start of LIST for which
-FORM evaluates to non-nil.
-This is the anaphoric counterpart to `-take-while'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result")))
-    `(let (,r)
-       (--each-while ,list ,form (push it ,r))
-       (nreverse ,r))))
-
-(defun -take-while (pred list)
-  "Take successive items from LIST for which PRED returns non-nil.
-PRED is a function of one argument.  Return a new list of the
-successive elements from the start of LIST for which PRED returns
-non-nil.
-
-This function's anaphoric counterpart is `--take-while'.
-
-For another variant, see also `-drop-while'."
-  (declare (important-return-value t))
-  (--take-while (funcall pred it) list))
-
-(defmacro --drop-while (form list)
-  "Drop successive items from LIST for which FORM evals to non-nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.  Return the
-tail (not a copy) of LIST starting from its first element for
-which FORM evaluates to nil.
-This is the anaphoric counterpart to `-drop-while'."
-  (declare (debug (form form)))
-  (let ((l (make-symbol "list")))
-    `(let ((,l ,list))
-       (--each-while ,l ,form (pop ,l))
-       ,l)))
-
-(defun -drop-while (pred list)
-  "Drop successive items from LIST for which PRED returns non-nil.
-PRED is a function of one argument.  Return the tail (not a copy)
-of LIST starting from its first element for which PRED returns
-nil.
-
-This function's anaphoric counterpart is `--drop-while'.
-
-For another variant, see also `-take-while'."
-  (declare (important-return-value t))
-  (--drop-while (funcall pred it) list))
-
-(defun -take (n list)
-  "Return a copy of the first N items in LIST.
-Return a copy of LIST if it contains N items or fewer.
-Return nil if N is zero or less.
-
-See also: `-take-last'."
-  (declare (side-effect-free t))
-  (--take-while (< it-index n) list))
-
-(defun -take-last (n list)
-  "Return a copy of the last N items of LIST in order.
-Return a copy of LIST if it contains N items or fewer.
-Return nil if N is zero or less.
-
-See also: `-take'."
-  (declare (side-effect-free t))
-  (copy-sequence (last list n)))
-
-(defalias '-drop #'nthcdr
-  "Return the tail (not a copy) of LIST without the first N items.
-Return nil if LIST contains N items or fewer.
-Return LIST if N is zero or less.
-
-For another variant, see also `-drop-last'.
-\n(fn N LIST)")
-
-(defun -drop-last (n list)
-  "Return a copy of LIST without its last N items.
-Return a copy of LIST if N is zero or less.
-Return nil if LIST contains N items or fewer.
-
-See also: `-drop'."
-  (declare (side-effect-free t))
-  (nbutlast (copy-sequence list) n))
-
-(defun -split-at (n list)
-  "Split LIST into two sublists after the Nth element.
-The result is a list of two elements (TAKE DROP) where TAKE is a
-new list of the first N elements of LIST, and DROP is the
-remaining elements of LIST (not a copy).  TAKE and DROP are like
-the results of `-take' and `-drop', respectively, but the split
-is done in a single list traversal."
-  (declare (side-effect-free t))
-  (let (result)
-    (--each-while list (< it-index n)
-      (push (pop list) result))
-    (list (nreverse result) list)))
-
-(defun -rotate (n list)
-  "Rotate LIST N places to the right (left if N is negative).
-The time complexity is O(n)."
-  (declare (pure t) (side-effect-free t))
-  (cond ((null list) ())
-        ((zerop n) (copy-sequence list))
-        ((let* ((len (length list))
-                (n-mod-len (mod n len))
-                (new-tail-len (- len n-mod-len)))
-           (append (nthcdr new-tail-len list) (-take new-tail-len list))))))
-
-(defun -insert-at (n x list)
-  "Return a list with X inserted into LIST at position N.
-
-See also: `-splice', `-splice-list'"
-  (declare (pure t) (side-effect-free t))
-  (let ((split-list (-split-at n list)))
-    (nconc (car split-list) (cons x (cadr split-list)))))
-
-(defun -replace-at (n x list)
-  "Return a list with element at Nth position in LIST replaced with X.
-
-See also: `-replace'"
-  (declare (pure t) (side-effect-free t))
-  (let ((split-list (-split-at n list)))
-    (nconc (car split-list) (cons x (cdr (cadr split-list))))))
-
-(defun -update-at (n func list)
-  "Use FUNC to update the Nth element of LIST.
-Return a copy of LIST where the Nth element is replaced with the
-result of calling FUNC on it.
-
-See also: `-map-when'"
-  (declare (important-return-value t))
-  (let ((split-list (-split-at n list)))
-    (nconc (car split-list)
-           (cons (funcall func (car (cadr split-list)))
-                 (cdr (cadr split-list))))))
-
-(defmacro --update-at (n form list)
-  "Anaphoric version of `-update-at'."
-  (declare (debug (form def-form form)))
-  `(-update-at ,n (lambda (it) (ignore it) ,form) ,list))
-
-(defun -remove-at (n list)
-  "Return LIST with its element at index N removed.
-That is, remove any element selected as (nth N LIST) from LIST
-and return the result.
-
-This is a non-destructive operation: parts of LIST (but not
-necessarily all of it) are copied as needed to avoid
-destructively modifying it.
-
-See also: `-remove-at-indices', `-remove'."
-  (declare (pure t) (side-effect-free t))
-  (if (zerop n)
-      (cdr list)
-    (--remove-first (= it-index n) list)))
-
-(defun -remove-at-indices (indices list)
-  "Return LIST with its elements at INDICES removed.
-That is, for each index I in INDICES, remove any element selected
-as (nth I LIST) from LIST.
-
-This is a non-destructive operation: parts of LIST (but not
-necessarily all of it) are copied as needed to avoid
-destructively modifying it.
-
-See also: `-remove-at', `-remove'."
-  (declare (pure t) (side-effect-free t))
-  (setq indices (--drop-while (< it 0) (-sort #'< indices)))
-  (let ((i (pop indices)) res)
-    (--each-while list i
-      (pop list)
-      (if (/= it-index i)
-          (push it res)
-        (while (and indices (= (car indices) i))
-          (pop indices))
-        (setq i (pop indices))))
-    (nconc (nreverse res) list)))
-
-(defmacro --split-with (pred list)
-  "Anaphoric form of `-split-with'."
-  (declare (debug (form form)))
-  (let ((l (make-symbol "list"))
-        (r (make-symbol "result"))
-        (c (make-symbol "continue")))
-    `(let ((,l ,list)
-           (,r nil)
-           (,c t))
-       (while (and ,l ,c)
-         (let ((it (car ,l)))
-           (if (not ,pred)
-               (setq ,c nil)
-             (!cons it ,r)
-             (!cdr ,l))))
-       (list (nreverse ,r) ,l))))
-
-(defun -split-with (pred list)
-  "Split LIST into a prefix satisfying PRED, and the rest.
-The first sublist is the prefix of LIST with successive elements
-satisfying PRED, and the second sublist is the remaining elements
-that do not.  The result is like performing
-
-  ((-take-while PRED LIST) (-drop-while PRED LIST))
-
-but in no more than a single pass through LIST."
-  (declare (important-return-value t))
-  (--split-with (funcall pred it) list))
-
-(defmacro -split-on (item list)
-  "Split the LIST each time ITEM is found.
-
-Unlike `-partition-by', the ITEM is discarded from the results.
-Empty lists are also removed from the result.
-
-Comparison is done by `equal'.
-
-See also `-split-when'"
-  (declare (debug (def-form form)))
-  `(-split-when (lambda (it) (equal it ,item)) ,list))
-
-(defmacro --split-when (form list)
-  "Anaphoric version of `-split-when'."
-  (declare (debug (def-form form)))
-  `(-split-when (lambda (it) (ignore it) ,form) ,list))
-
-(defun -split-when (fn list)
-  "Split the LIST on each element where FN returns non-nil.
-
-Unlike `-partition-by', the \"matched\" element is discarded from
-the results.  Empty lists are also removed from the result.
-
-This function can be thought of as a generalization of
-`split-string'."
-  (declare (important-return-value t))
-  (let (r s)
-    (while list
-      (if (not (funcall fn (car list)))
-          (push (car list) s)
-        (when s (push (nreverse s) r))
-        (setq s nil))
-      (!cdr list))
-    (when s (push (nreverse s) r))
-    (nreverse r)))
-
-(defmacro --separate (form list)
-  "Anaphoric form of `-separate'."
-  (declare (debug (form form)))
-  (let ((y (make-symbol "yes"))
-        (n (make-symbol "no")))
-    `(let (,y ,n)
-       (--each ,list (if ,form (!cons it ,y) (!cons it ,n)))
-       (list (nreverse ,y) (nreverse ,n)))))
-
-(defun -separate (pred list)
-  "Split LIST into two sublists based on whether items satisfy PRED.
-The result is like performing
-
-  ((-filter PRED LIST) (-remove PRED LIST))
-
-but in a single pass through LIST."
-  (declare (important-return-value t))
-  (--separate (funcall pred it) list))
-
-(defun dash--partition-all-in-steps-reversed (n step list)
-  "Like `-partition-all-in-steps', but the result is reversed."
-  (when (< step 1)
-    (signal 'wrong-type-argument
-            `("Step size < 1 results in juicy infinite loops" ,step)))
-  (let (result)
-    (while list
-      (push (-take n list) result)
-      (setq list (nthcdr step list)))
-    result))
-
-(defun -partition-all-in-steps (n step list)
-  "Partition LIST into sublists of length N that are STEP items apart.
-Adjacent groups may overlap if N exceeds the STEP stride.
-Trailing groups may contain less than N items."
-  (declare (pure t) (side-effect-free t))
-  (nreverse (dash--partition-all-in-steps-reversed n step list)))
-
-(defun -partition-in-steps (n step list)
-  "Partition LIST into sublists of length N that are STEP items apart.
-Like `-partition-all-in-steps', but if there are not enough items
-to make the last group N-sized, those items are discarded."
-  (declare (pure t) (side-effect-free t))
-  (let ((result (dash--partition-all-in-steps-reversed n step list)))
-    (while (and result (< (length (car result)) n))
-      (pop result))
-    (nreverse result)))
-
-(defun -partition-all (n list)
-  "Return a new list with the items in LIST grouped into N-sized sublists.
-The last group may contain less than N items."
-  (declare (pure t) (side-effect-free t))
-  (-partition-all-in-steps n n list))
-
-(defun -partition (n list)
-  "Return a new list with the items in LIST grouped into N-sized sublists.
-If there are not enough items to make the last group N-sized,
-those items are discarded."
-  (declare (pure t) (side-effect-free t))
-  (-partition-in-steps n n list))
-
-(defmacro --partition-by (form list)
-  "Anaphoric form of `-partition-by'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result"))
-        (s (make-symbol "sublist"))
-        (v (make-symbol "value"))
-        (n (make-symbol "new-value"))
-        (l (make-symbol "list")))
-    `(let ((,l ,list))
-       (when ,l
-         (let* ((,r nil)
-                (it (car ,l))
-                (,s (list it))
-                (,v ,form)
-                (,l (cdr ,l)))
-           (while ,l
-             (let* ((it (car ,l))
-                    (,n ,form))
-               (unless (equal ,v ,n)
-                 (!cons (nreverse ,s) ,r)
-                 (setq ,s nil)
-                 (setq ,v ,n))
-               (!cons it ,s)
-               (!cdr ,l)))
-           (!cons (nreverse ,s) ,r)
-           (nreverse ,r))))))
-
-(defun -partition-by (fn list)
-  "Apply FN to each item in LIST, splitting it each time FN returns a new value."
-  (declare (important-return-value t))
-  (--partition-by (funcall fn it) list))
-
-(defmacro --partition-by-header (form list)
-  "Anaphoric form of `-partition-by-header'."
-  (declare (debug (form form)))
-  (let ((r (make-symbol "result"))
-        (s (make-symbol "sublist"))
-        (h (make-symbol "header-value"))
-        (b (make-symbol "seen-body?"))
-        (n (make-symbol "new-value"))
-        (l (make-symbol "list")))
-    `(let ((,l ,list))
-       (when ,l
-         (let* ((,r nil)
-                (it (car ,l))
-                (,s (list it))
-                (,h ,form)
-                (,b nil)
-                (,l (cdr ,l)))
-           (while ,l
-             (let* ((it (car ,l))
-                    (,n ,form))
-               (if (equal ,h ,n)
-                   (when ,b
-                     (!cons (nreverse ,s) ,r)
-                     (setq ,s nil)
-                     (setq ,b nil))
-                 (setq ,b t))
-               (!cons it ,s)
-               (!cdr ,l)))
-           (!cons (nreverse ,s) ,r)
-           (nreverse ,r))))))
-
-(defun -partition-by-header (fn list)
-  "Apply FN to the first item in LIST. That is the header
-value. Apply FN to each item in LIST, splitting it each time FN
-returns the header value, but only after seeing at least one
-other value (the body)."
-  (declare (important-return-value t))
-  (--partition-by-header (funcall fn it) list))
-
-(defmacro --partition-after-pred (form list)
-  "Partition LIST after each element for which FORM evaluates to non-nil.
-Each element of LIST in turn is bound to `it' before evaluating
-FORM.
-
-This is the anaphoric counterpart to `-partition-after-pred'."
-  (let ((l (make-symbol "list"))
-        (r (make-symbol "result"))
-        (s (make-symbol "sublist")))
-    `(let ((,l ,list) ,r ,s)
-       (when ,l
-         (--each ,l
-           (push it ,s)
-           (when ,form
-             (push (nreverse ,s) ,r)
-             (setq ,s ())))
-         (when ,s
-           (push (nreverse ,s) ,r))
-         (nreverse ,r)))))
-
-(defun -partition-after-pred (pred list)
-  "Partition LIST after each element for which PRED returns non-nil.
-
-This function's anaphoric counterpart is `--partition-after-pred'."
-  (declare (important-return-value t))
-  (--partition-after-pred (funcall pred it) list))
-
-(defun -partition-before-pred (pred list)
-  "Partition directly before each time PRED is true on an element of LIST."
-  (declare (important-return-value t))
-  (nreverse (-map #'reverse
-                  (-partition-after-pred pred (reverse list)))))
-
-(defun -partition-after-item (item list)
-  "Partition directly after each time ITEM appears in LIST."
-  (declare (pure t) (side-effect-free t))
-  (-partition-after-pred (lambda (ele) (equal ele item))
-                         list))
-
-(defun -partition-before-item (item list)
-  "Partition directly before each time ITEM appears in LIST."
-  (declare (pure t) (side-effect-free t))
-  (-partition-before-pred (lambda (ele) (equal ele item))
-                          list))
-
-(defmacro --group-by (form list)
-  "Anaphoric form of `-group-by'."
-  (declare (debug t))
-  (let ((n (make-symbol "n"))
-        (k (make-symbol "k"))
-        (grp (make-symbol "grp")))
-    `(nreverse
-      (-map
-       (lambda (,n)
-         (cons (car ,n)
-               (nreverse (cdr ,n))))
-       (--reduce-from
-        (let* ((,k (,@form))
-               (,grp (assoc ,k acc)))
-          (if ,grp
-              (setcdr ,grp (cons it (cdr ,grp)))
-            (push
-             (list ,k it)
-             acc))
-          acc)
-        nil ,list)))))
-
-(defun -group-by (fn list)
-  "Separate LIST into an alist whose keys are FN applied to the
-elements of LIST.  Keys are compared by `equal'."
-  (declare (important-return-value t))
-  (--group-by (funcall fn it) list))
-
-(defun -interpose (sep list)
-  "Return a new list of all elements in LIST separated by SEP."
-  (declare (side-effect-free t))
-  (let (result)
-    (when list
-      (!cons (car list) result)
-      (!cdr list))
-    (while list
-      (setq result (cons (car list) (cons sep result)))
-      (!cdr list))
-    (nreverse result)))
-
-(defun -interleave (&rest lists)
-  "Return a new list of the first item in each list, then the second etc."
-  (declare (side-effect-free t))
-  (when lists
-    (let (result)
-      (while (-none? 'null lists)
-        (--each lists (!cons (car it) result))
-        (setq lists (-map 'cdr lists)))
-      (nreverse result))))
-
-(defmacro --zip-with (form list1 list2)
-  "Zip LIST1 and LIST2 into a new list according to FORM.
-That is, evaluate FORM for each item pair from the two lists, and
-return the list of results.  The result is as long as the shorter
-list.
-
-Each element of LIST1 and each element of LIST2 in turn are bound
-pairwise to `it' and `other', respectively, and their index
-within the list to `it-index', before evaluating FORM.
-
-This is the anaphoric counterpart to `-zip-with'."
-  (declare (debug (form form form)))
-  (let ((r (make-symbol "result"))
-        (l2 (make-symbol "list2")))
-    `(let ((,l2 ,list2) ,r)
-       (--each-while ,list1 ,l2
-         (let ((other (pop ,l2)))
-           (ignore other)
-           (push ,form ,r)))
-       (nreverse ,r))))
-
-(defun -zip-with (fn list1 list2)
-  "Zip LIST1 and LIST2 into a new list using the function FN.
-That is, apply FN pairwise taking as first argument the next
-element of LIST1 and as second argument the next element of LIST2
-at the corresponding position.  The result is as long as the
-shorter list.
-
-This function's anaphoric counterpart is `--zip-with'.
-
-For other zips, see also `-zip-lists' and `-zip-fill'."
-  (declare (important-return-value t))
-  (--zip-with (funcall fn it other) list1 list2))
-
-(defun -zip-lists (&rest lists)
-  "Zip LISTS together.
-
-Group the head of each list, followed by the second element of
-each list, and so on.  The number of returned groupings is equal
-to the length of the shortest input list, and the length of each
-grouping is equal to the number of input LISTS.
-
-The return value is always a list of proper lists, in contrast to
-`-zip' which returns a list of dotted pairs when only two input
-LISTS are provided.
-
-See also: `-zip-pair'."
-  (declare (pure t) (side-effect-free t))
-  (when lists
-    (let (results)
-      (while (--every it lists)
-        (push (mapcar #'car lists) results)
-        (setq lists (mapcar #'cdr lists)))
-      (nreverse results))))
-
-(defun -zip-lists-fill (fill-value &rest lists)
-  "Zip LISTS together, padding shorter lists with FILL-VALUE.
-This is like `-zip-lists' (which see), except it retains all
-elements at positions beyond the end of the shortest list.  The
-number of returned groupings is equal to the length of the
-longest input list, and the length of each grouping is equal to
-the number of input LISTS."
-  (declare (pure t) (side-effect-free t))
-  (when lists
-    (let (results)
-      (while (--some it lists)
-        (push (--map (if it (car it) fill-value) lists) results)
-        (setq lists (mapcar #'cdr lists)))
-      (nreverse results))))
-
-(defun -unzip-lists (lists)
-  "Unzip LISTS.
-
-This works just like `-zip-lists' (which see), but takes a list
-of lists instead of a variable number of arguments, such that
-
-  (-unzip-lists (-zip-lists ARGS...))
-
-is identity (given that the lists comprising ARGS are of the same
-length)."
-  (declare (pure t) (side-effect-free t))
-  (apply #'-zip-lists lists))
-
-(defalias 'dash--length=
-  (if (fboundp 'length=)
-      #'length=
-    (lambda (list length)
-      (cond ((< length 0) nil)
-            ((zerop length) (null list))
-            ((let ((last (nthcdr (1- length) list)))
-               (and last (null (cdr last))))))))
-  "Return non-nil if LIST is of LENGTH.
-This is a compatibility shim for `length=' in Emacs 28.
-\n(fn LIST LENGTH)")
-
-(defun dash--zip-lists-or-pair (_form &rest lists)
-  "Return a form equivalent to applying `-zip' to LISTS.
-This `compiler-macro' warns about discouraged `-zip' usage and
-delegates to `-zip-lists' or `-zip-pair' depending on the number
-of LISTS."
-  (if (not (dash--length= lists 2))
-      (cons #'-zip-lists lists)
-    (let ((pair (cons #'-zip-pair lists))
-          (msg "Use -zip-pair instead of -zip to get a list of pairs"))
-      (if (fboundp 'macroexp-warn-and-return)
-          (macroexp-warn-and-return msg pair)
-        (message msg)
-        pair))))
-
-(defun -zip (&rest lists)
-  "Zip LISTS together.
-
-Group the head of each list, followed by the second element of
-each list, and so on.  The number of returned groupings is equal
-to the length of the shortest input list, and the number of items
-in each grouping is equal to the number of input LISTS.
-
-If only two LISTS are provided as arguments, return the groupings
-as a list of dotted pairs.  Otherwise, return the groupings as a
-list of proper lists.
-
-Since the return value changes form depending on the number of
-arguments, it is generally recommended to use `-zip-lists'
-instead, or `-zip-pair' if a list of dotted pairs is desired.
-
-See also: `-unzip'."
-  (declare (compiler-macro dash--zip-lists-or-pair)
-           (pure t) (side-effect-free t))
-  ;; For backward compatibility, return a list of dotted pairs if two
-  ;; arguments were provided.
-  (apply (if (dash--length= lists 2) #'-zip-pair #'-zip-lists) lists))
-
-(defun -zip-pair (&rest lists)
-  "Zip LIST1 and LIST2 together.
-
-Make a pair with the head of each list, followed by a pair with
-the second element of each list, and so on.  The number of pairs
-returned is equal to the length of the shorter input list.
-
-See also: `-zip-lists'."
-  (declare (advertised-calling-convention (list1 list2) "2.20.0")
-           (pure t) (side-effect-free t))
-  (if (dash--length= lists 2)
-      (--zip-with (cons it other) (car lists) (cadr lists))
-    (apply #'-zip-lists lists)))
-
-(defun -zip-fill (fill-value &rest lists)
-  "Zip LISTS together, padding shorter lists with FILL-VALUE.
-This is like `-zip' (which see), except it retains all elements
-at positions beyond the end of the shortest list.  The number of
-returned groupings is equal to the length of the longest input
-list, and the length of each grouping is equal to the number of
-input LISTS.
-
-Since the return value changes form depending on the number of
-arguments, it is generally recommended to use `-zip-lists-fill'
-instead, unless a list of dotted pairs is explicitly desired."
-  (declare (pure t) (side-effect-free t))
-  (cond ((null lists) ())
-        ((dash--length= lists 2)
-         (let ((list1 (car lists))
-               (list2 (cadr lists))
-               results)
-           (while (or list1 list2)
-             (push (cons (if list1 (pop list1) fill-value)
-                         (if list2 (pop list2) fill-value))
-                   results))
-           (nreverse results)))
-        ((apply #'-zip-lists-fill fill-value lists))))
-
-(defun -unzip (lists)
-  "Unzip LISTS.
-
-This works just like `-zip' (which see), but takes a list of
-lists instead of a variable number of arguments, such that
-
-  (-unzip (-zip L1 L2 L3 ...))
-
-is identity (given that the lists are of the same length, and
-that `-zip' is not called with two arguments, because of the
-caveat described in its docstring).
-
-Note in particular that calling `-unzip' on a list of two lists
-will return a list of dotted pairs.
-
-Since the return value changes form depending on the number of
-LISTS, it is generally recommended to use `-unzip-lists' instead."
-  (declare (pure t) (side-effect-free t))
-  (apply #'-zip lists))
-
-(defun -cycle (list)
-  "Return an infinite circular copy of LIST.
-The returned list cycles through the elements of LIST and repeats
-from the beginning."
-  (declare (pure t) (side-effect-free t))
-  ;; Also works with sequences that aren't lists.
-  (let ((newlist (append list ())))
-    (nconc newlist newlist)))
-
-(defun -pad (fill-value &rest lists)
-  "Pad each of LISTS with FILL-VALUE until they all have equal lengths.
-
-Ensure all LISTS are as long as the longest one by repeatedly
-appending FILL-VALUE to the shorter lists, and return the
-resulting LISTS."
-  (declare (pure t) (side-effect-free t))
-  (let* ((lens (mapcar #'length lists))
-         (maxlen (apply #'max 0 lens)))
-    (--map (append it (make-list (- maxlen (pop lens)) fill-value)) lists)))
-
-(defmacro --annotate (form list)
-  "Pair each item in LIST with the result of evaluating FORM.
-
-Return an alist of (RESULT . ITEM), where each ITEM is the
-corresponding element of LIST, and RESULT is the value obtained
-by evaluating FORM with ITEM bound to `it'.
-
-This is the anaphoric counterpart to `-annotate'."
-  (declare (debug (form form)))
-  `(--map (cons ,form it) ,list))
-
-(defun -annotate (fn list)
-  "Pair each item in LIST with the result of passing it to FN.
-
-Return an alist of (RESULT . ITEM), where each ITEM is the
-corresponding element of LIST, and RESULT is the value obtained
-by calling FN on ITEM.
-
-This function's anaphoric counterpart is `--annotate'."
-  (declare (important-return-value t))
-  (--annotate (funcall fn it) list))
-
-(defun dash--table-carry (lists restore-lists &optional re)
-  "Helper for `-table' and `-table-flat'.
-
-If a list overflows, carry to the right and reset the list."
-  (while (not (or (car lists)
-                  (equal lists '(nil))))
-    (setcar lists (car restore-lists))
-    (pop (cadr lists))
-    (!cdr lists)
-    (!cdr restore-lists)
-    (when re
-      (push (nreverse (car re)) (cadr re))
-      (setcar re nil)
-      (!cdr re))))
-
-(defun -table (fn &rest lists)
-  "Compute outer product of LISTS using function FN.
-
-The function FN should have the same arity as the number of
-supplied lists.
-
-The outer product is computed by applying fn to all possible
-combinations created by taking one element from each list in
-order.  The dimension of the result is (length lists).
-
-See also: `-table-flat'"
-  (declare (important-return-value t))
-  (let ((restore-lists (copy-sequence lists))
-        (last-list (last lists))
-        (re (make-list (length lists) nil)))
-    (while (car last-list)
-      (let ((item (apply fn (-map 'car lists))))
-        (push item (car re))
-        (setcar lists (cdar lists)) ;; silence byte compiler
-        (dash--table-carry lists restore-lists re)))
-    (nreverse (car (last re)))))
-
-(defun -table-flat (fn &rest lists)
-  "Compute flat outer product of LISTS using function FN.
-
-The function FN should have the same arity as the number of
-supplied lists.
-
-The outer product is computed by applying fn to all possible
-combinations created by taking one element from each list in
-order.  The results are flattened, ignoring the tensor structure
-of the result.  This is equivalent to calling:
-
-  (-flatten-n (1- (length lists)) (apply \\='-table fn lists))
-
-but the implementation here is much more efficient.
-
-See also: `-flatten-n', `-table'"
-  (declare (important-return-value t))
-  (let ((restore-lists (copy-sequence lists))
-        (last-list (last lists))
-        re)
-    (while (car last-list)
-      (let ((item (apply fn (-map 'car lists))))
-        (push item re)
-        (setcar lists (cdar lists)) ;; silence byte compiler
-        (dash--table-carry lists restore-lists)))
-    (nreverse re)))
-
-(defmacro --find-index (form list)
-  "Return the first index in LIST for which FORM evals to non-nil.
-Return nil if no such index is found.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-find-index'."
-  (declare (debug (form form)))
-  `(--some (and ,form it-index) ,list))
-
-(defun -find-index (pred list)
-  "Return the index of the first item satisfying PRED in LIST.
-Return nil if no such item is found.
-
-PRED is called with one argument, the current list element, until
-it returns non-nil, at which point the search terminates.
-
-This function's anaphoric counterpart is `--find-index'.
-
-See also: `-first', `-find-last-index'."
-  (declare (important-return-value t))
-  (--find-index (funcall pred it) list))
-
-(defun -elem-index (elem list)
-  "Return the first index of ELEM in LIST.
-That is, the index within LIST of the first element that is
-`equal' to ELEM.  Return nil if there is no such element.
-
-See also: `-find-index'."
-  (declare (pure t) (side-effect-free t))
-  (--find-index (equal elem it) list))
-
-(defmacro --find-indices (form list)
-  "Return the list of indices in LIST for which FORM evals to non-nil.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-find-indices'."
-  (declare (debug (form form)))
-  `(--keep (and ,form it-index) ,list))
-
-(defun -find-indices (pred list)
-  "Return the list of indices in LIST satisfying PRED.
-
-Each element of LIST in turn is passed to PRED.  If the result is
-non-nil, the index of that element in LIST is included in the
-result.  The returned indices are in ascending order, i.e., in
-the same order as they appear in LIST.
-
-This function's anaphoric counterpart is `--find-indices'.
-
-See also: `-find-index', `-elem-indices'."
-  (declare (important-return-value t))
-  (--find-indices (funcall pred it) list))
-
-(defun -elem-indices (elem list)
-  "Return the list of indices at which ELEM appears in LIST.
-That is, the indices of all elements of LIST `equal' to ELEM, in
-the same ascending order as they appear in LIST."
-  (declare (pure t) (side-effect-free t))
-  (--find-indices (equal elem it) list))
-
-(defmacro --find-last-index (form list)
-  "Return the last index in LIST for which FORM evals to non-nil.
-Return nil if no such index is found.
-Each element of LIST in turn is bound to `it' and its index
-within LIST to `it-index' before evaluating FORM.
-This is the anaphoric counterpart to `-find-last-index'."
-  (declare (debug (form form)))
-  (let ((i (make-symbol "index")))
-    `(let (,i)
-       (--each ,list
-         (when ,form (setq ,i it-index)))
-       ,i)))
-
-(defun -find-last-index (pred list)
-  "Return the index of the last item satisfying PRED in LIST.
-Return nil if no such item is found.
-
-Predicate PRED is called with one argument each time, namely the
-current list element.
-
-This function's anaphoric counterpart is `--find-last-index'.
-
-See also: `-last', `-find-index'."
-  (declare (important-return-value t))
-  (--find-last-index (funcall pred it) list))
-
-(defun -select-by-indices (indices list)
-  "Return a list whose elements are elements from LIST selected
-as `(nth i list)` for all i from INDICES."
-  (declare (pure t) (side-effect-free t))
-  (let (r)
-    (--each indices
-      (!cons (nth it list) r))
-    (nreverse r)))
-
-(defun -select-columns (columns table)
-  "Select COLUMNS from TABLE.
-
-TABLE is a list of lists where each element represents one row.
-It is assumed each row has the same length.
-
-Each row is transformed such that only the specified COLUMNS are
-selected.
-
-See also: `-select-column', `-select-by-indices'"
-  (declare (pure t) (side-effect-free t))
-  (--map (-select-by-indices columns it) table))
-
-(defun -select-column (column table)
-  "Select COLUMN from TABLE.
-
-TABLE is a list of lists where each element represents one row.
-It is assumed each row has the same length.
-
-The single selected column is returned as a list.
-
-See also: `-select-columns', `-select-by-indices'"
-  (declare (pure t) (side-effect-free t))
-  (--mapcat (-select-by-indices (list column) it) table))
-
-(defmacro -> (x &optional form &rest more)
-  "Thread the expr through the forms. Insert X as the second item
-in the first form, making a list of it if it is not a list
-already. If there are more forms, insert the first form as the
-second item in second form, etc."
-  (declare (debug (form &rest [&or symbolp (sexp &rest form)])))
-  (cond
-   ((null form) x)
-   ((null more) (if (listp form)
-                    `(,(car form) ,x ,@(cdr form))
-                  (list form x)))
-   (:else `(-> (-> ,x ,form) ,@more))))
-
-(defmacro ->> (x &optional form &rest more)
-  "Thread the expr through the forms. Insert X as the last item
-in the first form, making a list of it if it is not a list
-already. If there are more forms, insert the first form as the
-last item in second form, etc."
-  (declare (debug ->))
-  (cond
-   ((null form) x)
-   ((null more) (if (listp form)
-                    `(,@form ,x)
-                  (list form x)))
-   (:else `(->> (->> ,x ,form) ,@more))))
-
-(defmacro --> (x &rest forms)
-  "Starting with the value of X, thread each expression through FORMS.
-
-Insert X at the position signified by the symbol `it' in the first
-form.  If there are more forms, insert the first form at the position
-signified by `it' in the second form, etc."
-  (declare (debug (form body)))
-  `(-as-> ,x it ,@forms))
-
-(defmacro -as-> (value variable &rest forms)
-  "Starting with VALUE, thread VARIABLE through FORMS.
-
-In the first form, bind VARIABLE to VALUE.  In the second form, bind
-VARIABLE to the result of the first form, and so forth."
-  (declare (debug (form symbolp body)))
-  (if (null forms)
-      `,value
-    `(let ((,variable ,value))
-       (-as-> ,(if (symbolp (car forms))
-                   (list (car forms) variable)
-                 (car forms))
-              ,variable
-              ,@(cdr forms)))))
-
-(defmacro -some-> (x &optional form &rest more)
-  "When expr is non-nil, thread it through the first form (via `->'),
-and when that result is non-nil, through the next form, etc."
-  (declare (debug ->)
-           (indent 1))
-  (if (null form) x
-    (let ((result (make-symbol "result")))
-      `(-some-> (-when-let (,result ,x)
-                  (-> ,result ,form))
-         ,@more))))
-
-(defmacro -some->> (x &optional form &rest more)
-  "When expr is non-nil, thread it through the first form (via `->>'),
-and when that result is non-nil, through the next form, etc."
-  (declare (debug ->)
-           (indent 1))
-  (if (null form) x
-    (let ((result (make-symbol "result")))
-      `(-some->> (-when-let (,result ,x)
-                   (->> ,result ,form))
-         ,@more))))
-
-(defmacro -some--> (expr &rest forms)
-  "Thread EXPR through FORMS via `-->', while the result is non-nil.
-When EXPR evaluates to non-nil, thread the result through the
-first of FORMS, and when that result is non-nil, thread it
-through the next form, etc."
-  (declare (debug (form &rest &or symbolp consp)) (indent 1))
-  (if (null forms) expr
-    (let ((result (make-symbol "result")))
-      `(-some--> (-when-let (,result ,expr)
-                   (--> ,result ,(car forms)))
-         ,@(cdr forms)))))
-
-(defmacro -doto (init &rest forms)
-  "Evaluate INIT and pass it as argument to FORMS with `->'.
-The RESULT of evaluating INIT is threaded through each of FORMS
-individually using `->', which see.  The return value is RESULT,
-which FORMS may have modified by side effect."
-  (declare (debug (form &rest &or symbolp consp)) (indent 1))
-  (let ((retval (make-symbol "result")))
-    `(let ((,retval ,init))
-       ,@(mapcar (lambda (form) `(-> ,retval ,form)) forms)
-       ,retval)))
-
-(defmacro --doto (init &rest forms)
-  "Anaphoric form of `-doto'.
-This just evaluates INIT, binds the result to `it', evaluates
-FORMS, and returns the final value of `it'.
-Note: `it' need not be used in each form."
-  (declare (debug (form body)) (indent 1))
-  `(let ((it ,init))
-     ,@forms
-     it))
-
-(defun -grade-up (comparator list)
-  "Grade elements of LIST using COMPARATOR relation.
-This yields a permutation vector such that applying this
-permutation to LIST sorts it in ascending order."
-  (declare (important-return-value t))
-  (->> (--map-indexed (cons it it-index) list)
-       (-sort (lambda (it other) (funcall comparator (car it) (car other))))
-       (mapcar #'cdr)))
-
-(defun -grade-down (comparator list)
-  "Grade elements of LIST using COMPARATOR relation.
-This yields a permutation vector such that applying this
-permutation to LIST sorts it in descending order."
-  (declare (important-return-value t))
-  (->> (--map-indexed (cons it it-index) list)
-       (-sort (lambda (it other) (funcall comparator (car other) (car it))))
-       (mapcar #'cdr)))
-
-(defvar dash--source-counter 0
-  "Monotonic counter for generated symbols.")
-
-(defun dash--match-make-source-symbol ()
-  "Generate a new dash-source symbol.
-
-All returned symbols are guaranteed to be unique."
-  (prog1 (make-symbol (format "--dash-source-%d--" dash--source-counter))
-    (setq dash--source-counter (1+ dash--source-counter))))
-
-(defun dash--match-ignore-place-p (symbol)
-  "Return non-nil if SYMBOL is a symbol and starts with _."
-  (and (symbolp symbol)
-       (eq (aref (symbol-name symbol) 0) ?_)))
-
-(defun dash--match-cons-skip-cdr (skip-cdr source)
-  "Helper function generating idiomatic shifting code."
-  (cond
-   ((= skip-cdr 0)
-    `(pop ,source))
-   (t
-    `(prog1 ,(dash--match-cons-get-car skip-cdr source)
-       (setq ,source ,(dash--match-cons-get-cdr (1+ skip-cdr) source))))))
-
-(defun dash--match-cons-get-car (skip-cdr source)
-  "Helper function generating idiomatic code to get nth car."
-  (cond
-   ((= skip-cdr 0)
-    `(car ,source))
-   ((= skip-cdr 1)
-    `(cadr ,source))
-   (t
-    `(nth ,skip-cdr ,source))))
-
-(defun dash--match-cons-get-cdr (skip-cdr source)
-  "Helper function generating idiomatic code to get nth cdr."
-  (cond
-   ((= skip-cdr 0)
-    source)
-   ((= skip-cdr 1)
-    `(cdr ,source))
-   (t
-    `(nthcdr ,skip-cdr ,source))))
-
-(defun dash--match-cons (match-form source)
-  "Setup a cons matching environment and call the real matcher."
-  (let ((s (dash--match-make-source-symbol))
-        (n 0)
-        (m match-form))
-    (while (and (consp m)
-                (dash--match-ignore-place-p (car m)))
-      (setq n (1+ n)) (!cdr m))
-    (cond
-     ;; when we only have one pattern in the list, we don't have to
-     ;; create a temporary binding (--dash-source--) for the source
-     ;; and just use the input directly
-     ((and (consp m)
-           (not (cdr m)))
-      (dash--match (car m) (dash--match-cons-get-car n source)))
-     ;; handle other special types
-     ((> n 0)
-      (dash--match m (dash--match-cons-get-cdr n source)))
-     ;; this is the only entry-point for dash--match-cons-1, that's
-     ;; why we can't simply use the above branch, it would produce
-     ;; infinite recursion
-     (t
-      (cons (list s source) (dash--match-cons-1 match-form s))))))
-
-(defun dash--get-expand-function (type)
-  "Get expand function name for TYPE."
-  (intern-soft (format "dash-expand:%s" type)))
-
-(defun dash--match-cons-1 (match-form source &optional props)
-  "Match MATCH-FORM against SOURCE.
-
-MATCH-FORM is a proper or improper list.  Each element of
-MATCH-FORM is either a symbol, which gets bound to the respective
-value in source or another match form which gets destructured
-recursively.
-
-If the cdr of last cons cell in the list is nil, matching stops
-there.
-
-SOURCE is a proper or improper list."
-  (let ((skip-cdr (or (plist-get props :skip-cdr) 0)))
-    (cond
-     ((consp match-form)
-      (cond
-       ((cdr match-form)
-        (cond
-         ((and (symbolp (car match-form))
-               (functionp (dash--get-expand-function (car match-form))))
-          (dash--match-kv (dash--match-kv-normalize-match-form match-form) (dash--match-cons-get-cdr skip-cdr source)))
-         ((dash--match-ignore-place-p (car match-form))
-          (dash--match-cons-1 (cdr match-form) source
-                              (plist-put props :skip-cdr (1+ skip-cdr))))
-         (t
-          (-concat (dash--match (car match-form) (dash--match-cons-skip-cdr skip-cdr source))
-                   (dash--match-cons-1 (cdr match-form) source)))))
-       (t ;; Last matching place, no need for shift
-        (dash--match (car match-form) (dash--match-cons-get-car skip-cdr source)))))
-     ((eq match-form nil)
-      nil)
-     (t ;; Handle improper lists.  Last matching place, no need for shift
-      (dash--match match-form (dash--match-cons-get-cdr skip-cdr source))))))
-
-(defun dash--match-vector (match-form source)
-  "Setup a vector matching environment and call the real matcher."
-  (let ((s (dash--match-make-source-symbol)))
-    (cond
-     ;; don't bind `s' if we only have one sub-pattern
-     ((= (length match-form) 1)
-      (dash--match (aref match-form 0) `(aref ,source 0)))
-     ;; if the source is a symbol, we don't need to re-bind it
-     ((symbolp source)
-      (dash--match-vector-1 match-form source))
-     ;; don't bind `s' if we only have one sub-pattern which is not ignored
-     ((let* ((ignored-places (mapcar 'dash--match-ignore-place-p match-form))
-             (ignored-places-n (length (-remove 'null ignored-places))))
-        (when (= ignored-places-n (1- (length match-form)))
-          (let ((n (-find-index 'null ignored-places)))
-            (dash--match (aref match-form n) `(aref ,source ,n))))))
-     (t
-      (cons (list s source) (dash--match-vector-1 match-form s))))))
-
-(defun dash--match-vector-1 (match-form source)
-  "Match MATCH-FORM against SOURCE.
-
-MATCH-FORM is a vector.  Each element of MATCH-FORM is either a
-symbol, which gets bound to the respective value in source or
-another match form which gets destructured recursively.
-
-If second-from-last place in MATCH-FORM is the symbol &rest, the
-next element of the MATCH-FORM is matched against the tail of
-SOURCE, starting at index of the &rest symbol.  This is
-conceptually the same as the (head . tail) match for improper
-lists, where dot plays the role of &rest.
-
-SOURCE is a vector.
-
-If the MATCH-FORM vector is shorter than SOURCE vector, only
-the (length MATCH-FORM) places are bound, the rest of the SOURCE
-is discarded."
-  (let ((i 0)
-        (l (length match-form))
-        (re))
-    (while (< i l)
-      (let ((m (aref match-form i)))
-        (push (cond
-               ((and (symbolp m)
-                     (eq m '&rest))
-                (prog1 (dash--match
-                        (aref match-form (1+ i))
-                        `(substring ,source ,i))
-                  (setq i l)))
-               ((and (symbolp m)
-                     ;; do not match symbols starting with _
-                     (not (eq (aref (symbol-name m) 0) ?_)))
-                (list (list m `(aref ,source ,i))))
-               ((not (symbolp m))
-                (dash--match m `(aref ,source ,i))))
-              re)
-        (setq i (1+ i))))
-    (-flatten-n 1 (nreverse re))))
-
-(defun dash--match-kv-normalize-match-form (pattern)
-  "Normalize kv PATTERN.
-
-This method normalizes PATTERN to the format expected by
-`dash--match-kv'.  See `-let' for the specification."
-  (let ((normalized (list (car pattern)))
-        (skip nil)
-        (fill-placeholder (make-symbol "--dash-fill-placeholder--")))
-    (-each (-zip-fill fill-placeholder (cdr pattern) (cddr pattern))
-      (lambda (pair)
-        (let ((current (car pair))
-              (next (cdr pair)))
-          (if skip
-              (setq skip nil)
-            (if (or (eq fill-placeholder next)
-                    (not (or (and (symbolp next)
-                                  (not (keywordp next))
-                                  (not (eq next t))
-                                  (not (eq next nil)))
-                             (and (consp next)
-                                  (not (eq (car next) 'quote)))
-                             (vectorp next))))
-                (progn
-                  (cond
-                   ((keywordp current)
-                    (push current normalized)
-                    (push (intern (substring (symbol-name current) 1)) normalized))
-                   ((stringp current)
-                    (push current normalized)
-                    (push (intern current) normalized))
-                   ((and (consp current)
-                         (eq (car current) 'quote))
-                    (push current normalized)
-                    (push (cadr current) normalized))
-                   (t (error "-let: found key `%s' in kv destructuring but its pattern `%s' is invalid and can not be derived from the key" current next)))
-                  (setq skip nil))
-              (push current normalized)
-              (push next normalized)
-              (setq skip t))))))
-    (nreverse normalized)))
-
-(defun dash--match-kv (match-form source)
-  "Setup a kv matching environment and call the real matcher.
-
-kv can be any key-value store, such as plist, alist or hash-table."
-  (let ((s (dash--match-make-source-symbol)))
-    (cond
-     ;; don't bind `s' if we only have one sub-pattern (&type key val)
-     ((= (length match-form) 3)
-      (dash--match-kv-1 (cdr match-form) source (car match-form)))
-     ;; if the source is a symbol, we don't need to re-bind it
-     ((symbolp source)
-      (dash--match-kv-1 (cdr match-form) source (car match-form)))
-     (t
-      (cons (list s source) (dash--match-kv-1 (cdr match-form) s (car match-form)))))))
-
-(defun dash-expand:&hash (key source)
-  "Generate extracting KEY from SOURCE for &hash destructuring."
-  `(gethash ,key ,source))
-
-(defun dash-expand:&plist (key source)
-  "Generate extracting KEY from SOURCE for &plist destructuring."
-  `(plist-get ,source ,key))
-
-(defun dash-expand:&alist (key source)
-  "Generate extracting KEY from SOURCE for &alist destructuring."
-  `(cdr (assoc ,key ,source)))
-
-(defun dash-expand:&hash? (key source)
-  "Generate extracting KEY from SOURCE for &hash? destructuring.
-Similar to &hash but check whether the map is not nil."
-  (let ((src (make-symbol "src")))
-    `(let ((,src ,source))
-       (when ,src (gethash ,key ,src)))))
-
-(defalias 'dash-expand:&keys 'dash-expand:&plist)
-
-(defun dash--match-kv-1 (match-form source type)
-  "Match MATCH-FORM against SOURCE of type TYPE.
-
-MATCH-FORM is a proper list of the form (key1 place1 ... keyN
-placeN).  Each placeK is either a symbol, which gets bound to the
-value of keyK retrieved from the key-value store, or another
-match form which gets destructured recursively.
-
-SOURCE is a key-value store of type TYPE, which can be a plist,
-an alist or a hash table.
-
-TYPE is a token specifying the type of the key-value store.
-Valid values are &plist, &alist and &hash."
-  (-flatten-n 1 (-map
-                 (lambda (kv)
-                   (let* ((k (car kv))
-                          (v (cadr kv))
-                          (getter
-                           (funcall (dash--get-expand-function type) k source)))
-                     (cond
-                      ((symbolp v)
-                       (list (list v getter)))
-                      (t (dash--match v getter)))))
-                 (-partition 2 match-form))))
-
-(defun dash--match-symbol (match-form source)
-  "Bind a symbol.
-
-This works just like `let', there is no destructuring."
-  (list (list match-form source)))
-
-(defun dash--match (match-form source)
-  "Match MATCH-FORM against SOURCE.
-
-This function tests the MATCH-FORM and dispatches to specific
-matchers based on the type of the expression.
-
-Key-value stores are disambiguated by placing a token &plist,
-&alist or &hash as a first item in the MATCH-FORM."
-  (cond
-   ((and (symbolp match-form)
-         ;; Don't bind things like &keys as if they were vars (#395).
-         (not (functionp (dash--get-expand-function match-form))))
-    (dash--match-symbol match-form source))
-   ((consp match-form)
-    (cond
-     ;; Handle the "x &as" bindings first.
-     ((and (consp (cdr match-form))
-           (symbolp (car match-form))
-           (eq '&as (cadr match-form)))
-      (let ((s (car match-form)))
-        (cons (list s source)
-              (dash--match (cddr match-form) s))))
-     ((functionp (dash--get-expand-function (car match-form)))
-      (dash--match-kv (dash--match-kv-normalize-match-form match-form) source))
-     (t (dash--match-cons match-form source))))
-   ((vectorp match-form)
-    ;; We support the &as binding in vectors too
-    (cond
-     ((and (> (length match-form) 2)
-           (symbolp (aref match-form 0))
-           (eq '&as (aref match-form 1)))
-      (let ((s (aref match-form 0)))
-        (cons (list s source)
-              (dash--match (substring match-form 2) s))))
-     (t (dash--match-vector match-form source))))))
-
-(defun dash--normalize-let-varlist (varlist)
-  "Normalize VARLIST so that every binding is a list.
-
-`let' allows specifying a binding which is not a list but simply
-the place which is then automatically bound to nil, such that all
-three of the following are identical and evaluate to nil.
-
-  (let (a) a)
-  (let ((a)) a)
-  (let ((a nil)) a)
-
-This function normalizes all of these to the last form."
-  (--map (if (consp it) it (list it nil)) varlist))
-
-(defmacro -let* (varlist &rest body)
-  "Bind variables according to VARLIST then eval BODY.
-
-VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
-PATTERN is matched against the SOURCE structurally.  SOURCE is
-only evaluated once for each PATTERN.
-
-Each SOURCE can refer to the symbols already bound by this
-VARLIST.  This is useful if you want to destructure SOURCE
-recursively but also want to name the intermediate structures.
-
-See `-let' for the list of all possible patterns."
-  (declare (debug ((&rest [&or (sexp form) sexp]) body))
-           (indent 1))
-  (let* ((varlist (dash--normalize-let-varlist varlist))
-         (bindings (--mapcat (dash--match (car it) (cadr it)) varlist)))
-    `(let* ,bindings
-       ,@body)))
-
-(defmacro -let (varlist &rest body)
-  "Bind variables according to VARLIST then eval BODY.
-
-VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
-PATTERN is matched against the SOURCE \"structurally\".  SOURCE
-is only evaluated once for each PATTERN.  Each PATTERN is matched
-recursively, and can therefore contain sub-patterns which are
-matched against corresponding sub-expressions of SOURCE.
-
-All the SOURCEs are evalled before any symbols are
-bound (i.e. \"in parallel\").
-
-If VARLIST only contains one (PATTERN SOURCE) element, you can
-optionally specify it using a vector and discarding the
-outer-most parens.  Thus
-
-  (-let ((PATTERN SOURCE)) ...)
-
-becomes
-
-  (-let [PATTERN SOURCE] ...).
-
-`-let' uses a convention of not binding places (symbols) starting
-with _ whenever it's possible.  You can use this to skip over
-entries you don't care about.  However, this is not *always*
-possible (as a result of implementation) and these symbols might
-get bound to undefined values.
-
-Following is the overview of supported patterns.  Remember that
-patterns can be matched recursively, so every a, b, aK in the
-following can be a matching construct and not necessarily a
-symbol/variable.
-
-Symbol:
-
-  a - bind the SOURCE to A.  This is just like regular `let'.
-
-Conses and lists:
-
-  (a) - bind `car' of cons/list to A
-
-  (a . b) - bind car of cons to A and `cdr' to B
-
-  (a b) - bind car of list to A and `cadr' to B
-
-  (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3...
-
-  (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST.
-
-Vectors:
-
-  [a] - bind 0th element of a non-list sequence to A (works with
-        vectors, strings, bit arrays...)
-
-  [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st to
-                   A1, 2nd to A2, ...
-                   If the PATTERN is shorter than SOURCE, the values at
-                   places not in PATTERN are ignored.
-                   If the PATTERN is longer than SOURCE, an `error' is
-                   thrown.
-
-  [a1 a2 a3 ... &rest rest] - as above, but bind the rest of
-                              the sequence to REST.  This is
-                              conceptually the same as improper list
-                              matching (a1 a2 ... aN . rest)
-
-Key/value stores:
-
-  (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
-                                 SOURCE plist to aK.  If the
-                                 value is not found, aK is nil.
-                                 Uses `plist-get' to fetch values.
-
-  (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the
-                                 SOURCE alist to aK.  If the
-                                 value is not found, aK is nil.
-                                 Uses `assoc' to fetch values.
-
-  (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the
-                                SOURCE hash table to aK.  If the
-                                value is not found, aK is nil.
-                                Uses `gethash' to fetch values.
-
-Further, special keyword &keys supports \"inline\" matching of
-plist-like key-value pairs, similarly to &keys keyword of
-`cl-defun'.
-
-  (a1 a2 ... aN &keys key1 b1 ... keyN bK)
-
-This binds N values from the list to a1 ... aN, then interprets
-the cdr as a plist (see key/value matching above).
-
-A shorthand notation for kv-destructuring exists which allows the
-patterns be optionally left out and derived from the key name in
-the following fashion:
-
-- a key :foo is converted into `foo' pattern,
-- a key \\='bar is converted into `bar' pattern,
-- a key \"baz\" is converted into `baz' pattern.
-
-That is, the entire value under the key is bound to the derived
-variable without any further destructuring.
-
-This is possible only when the form following the key is not a
-valid pattern (i.e. not a symbol, a cons cell or a vector).
-Otherwise the matching proceeds as usual and in case of an
-invalid spec fails with an error.
-
-Thus the patterns are normalized as follows:
-
-   ;; derive all the missing patterns
-   (&plist :foo \\='bar \"baz\") => (&plist :foo foo \\='bar bar \"baz\" baz)
-
-   ;; we can specify some but not others
-   (&plist :foo \\='bar explicit-bar) => (&plist :foo foo \\='bar explicit-bar)
-
-   ;; nothing happens, we store :foo in x
-   (&plist :foo x) => (&plist :foo x)
-
-   ;; nothing happens, we match recursively
-   (&plist :foo (a b c)) => (&plist :foo (a b c))
-
-You can name the source using the syntax SYMBOL &as PATTERN.
-This syntax works with lists (proper or improper), vectors and
-all types of maps.
-
-  (list &as a b c) (list 1 2 3)
-
-binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
-
-Similarly:
-
-  (bounds &as beg . end) (cons 1 2)
-
-binds BEG to 1, END to 2 and BOUNDS to (1 . 2).
-
-  (items &as first . rest) (list 1 2 3)
-
-binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
-
-  [vect &as _ b c] [1 2 3]
-
-binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as usual).
-
-  (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
-
-binds B to 2 and PLIST to (:a 1 :b 2 :c 3).  Same for &alist and &hash.
-
-This is especially useful when we want to capture the result of a
-computation and destructure at the same time.  Consider the
-form (function-returning-complex-structure) returning a list of
-two vectors with two items each.  We want to capture this entire
-result and pass it to another computation, but at the same time
-we want to get the second item from each vector.  We can achieve
-it with pattern
-
-  (result &as [_ a] [_ b]) (function-returning-complex-structure)
-
-Note: Clojure programmers may know this feature as the \":as
-binding\".  The difference is that we put the &as at the front
-because we need to support improper list binding."
-  (declare (debug ([&or (&rest [&or (sexp form) sexp])
-                        (vector [&rest [sexp form]])]
-                   body))
-           (indent 1))
-  (if (vectorp varlist)
-      `(let* ,(dash--match (aref varlist 0) (aref varlist 1))
-         ,@body)
-    (let* ((varlist (dash--normalize-let-varlist varlist))
-           (inputs (--map-indexed (list (make-symbol (format "input%d" it-index)) (cadr it)) varlist))
-           (new-varlist (--zip-with (list (car it) (car other))
-                                    varlist inputs)))
-      `(let ,inputs
-         (-let* ,new-varlist ,@body)))))
-
-(defmacro -lambda (match-form &rest body)
-  "Return a lambda which destructures its input as MATCH-FORM and executes BODY.
-
-Note that you have to enclose the MATCH-FORM in a pair of parens,
-such that:
-
-  (-lambda (x) body)
-  (-lambda (x y ...) body)
-
-has the usual semantics of `lambda'.  Furthermore, these get
-translated into normal `lambda', so there is no performance
-penalty.
-
-See `-let' for a description of the destructuring mechanism."
-  (declare (doc-string 2) (indent defun)
-           (debug (&define sexp
-                           [&optional stringp]
-                           [&optional ("interactive" interactive)]
-                           def-body)))
-  (cond
-   ((nlistp match-form)
-    (signal 'wrong-type-argument (list #'listp match-form)))
-   ;; No destructuring, so just return regular `lambda' for speed.
-   ((-all? #'symbolp match-form)
-    `(lambda ,match-form ,@body))
-   ((let ((inputs (--map-indexed
-                   (list it (make-symbol (format "input%d" it-index)))
-                   match-form)))
-      ;; TODO: because inputs to the `lambda' are evaluated only once,
-      ;; `-let*' need not create the extra bindings to ensure that.
-      ;; We should find a way to optimize that.  Not critical however.
-      `(lambda ,(mapcar #'cadr inputs)
-         (-let* ,inputs ,@body))))))
-
-(defmacro -setq (&rest forms)
-  "Bind each MATCH-FORM to the value of its VAL.
-
-MATCH-FORM destructuring is done according to the rules of `-let'.
-
-This macro allows you to bind multiple variables by destructuring
-the value, so for example:
-
-  (-setq (a b) x
-         (&plist :c c) plist)
-
-expands roughly speaking to the following code
-
-  (setq a (car x)
-        b (cadr x)
-        c (plist-get plist :c))
-
-Care is taken to only evaluate each VAL once so that in case of
-multiple assignments it does not cause unexpected side effects.
-
-\(fn [MATCH-FORM VAL]...)"
-  (declare (debug (&rest sexp form))
-           (indent 1))
-  (when (= (mod (length forms) 2) 1)
-    (signal 'wrong-number-of-arguments (list '-setq (1+ (length forms)))))
-  (let* ((forms-and-sources
-          ;; First get all the necessary mappings with all the
-          ;; intermediate bindings.
-          (-map (lambda (x) (dash--match (car x) (cadr x)))
-                (-partition 2 forms)))
-         ;; To preserve the logic of dynamic scoping we must ensure
-         ;; that we `setq' the variables outside of the `let*' form
-         ;; which holds the destructured intermediate values.  For
-         ;; this we generate for each variable a placeholder which is
-         ;; bound to (lexically) the result of the destructuring.
-         ;; Then outside of the helper `let*' form we bind all the
-         ;; original variables to their respective placeholders.
-         ;; TODO: There is a lot of room for possible optimization,
-         ;; for start playing with `special-variable-p' to eliminate
-         ;; unnecessary re-binding.
-         (variables-to-placeholders
-          (-mapcat
-           (lambda (bindings)
-             (-map
-              (lambda (binding)
-                (let ((var (car binding)))
-                  (list var (make-symbol (concat "--dash-binding-" (symbol-name var) "--")))))
-              (--filter (not (string-prefix-p "--" (symbol-name (car it)))) bindings)))
-           forms-and-sources)))
-    `(let ,(-map 'cadr variables-to-placeholders)
-       (let* ,(-flatten-n 1 forms-and-sources)
-         (setq ,@(-flatten (-map 'reverse variables-to-placeholders))))
-       (setq ,@(-flatten variables-to-placeholders)))))
-
-(defmacro -if-let* (vars-vals then &rest else)
-  "If all VALS evaluate to true, bind them to their corresponding
-VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list
-of (VAR VAL) pairs.
-
-Note: binding is done according to `-let*'.  VALS are evaluated
-sequentially, and evaluation stops after the first nil VAL is
-encountered."
-  (declare (debug ((&rest (sexp form)) form body))
-           (indent 2))
-  (->> vars-vals
-       (--mapcat (dash--match (car it) (cadr it)))
-       (--reduce-r-from
-        (let ((var (car it))
-              (val (cadr it)))
-          `(let ((,var ,val))
-             (if ,var ,acc ,@else)))
-        then)))
-
-(defmacro -if-let (var-val then &rest else)
-  "If VAL evaluates to non-nil, bind it to VAR and do THEN,
-otherwise do ELSE.
-
-Note: binding is done according to `-let'.
-
-\(fn (VAR VAL) THEN &rest ELSE)"
-  (declare (debug ((sexp form) form body))
-           (indent 2))
-  `(-if-let* (,var-val) ,then ,@else))
-
-(defmacro --if-let (val then &rest else)
-  "If VAL evaluates to non-nil, bind it to symbol `it' and do THEN,
-otherwise do ELSE."
-  (declare (debug (form form body))
-           (indent 2))
-  `(-if-let (it ,val) ,then ,@else))
-
-(defmacro -when-let* (vars-vals &rest body)
-  "If all VALS evaluate to true, bind them to their corresponding
-VARS and execute body. VARS-VALS should be a list of (VAR VAL)
-pairs.
-
-Note: binding is done according to `-let*'.  VALS are evaluated
-sequentially, and evaluation stops after the first nil VAL is
-encountered."
-  (declare (debug ((&rest (sexp form)) body))
-           (indent 1))
-  `(-if-let* ,vars-vals (progn ,@body)))
-
-(defmacro -when-let (var-val &rest body)
-  "If VAL evaluates to non-nil, bind it to VAR and execute body.
-
-Note: binding is done according to `-let'.
-
-\(fn (VAR VAL) &rest BODY)"
-  (declare (debug ((sexp form) body))
-           (indent 1))
-  `(-if-let ,var-val (progn ,@body)))
-
-(defmacro --when-let (val &rest body)
-  "If VAL evaluates to non-nil, bind it to symbol `it' and
-execute body."
-  (declare (debug (form body))
-           (indent 1))
-  `(--if-let ,val (progn ,@body)))
-
-;; TODO: Get rid of this dynamic variable, passing it as an argument
-;; instead?
-(defvar -compare-fn nil
-  "Tests for equality use this function, or `equal' if this is nil.
-
-As a dynamic variable, this should be temporarily bound around
-the relevant operation, rather than permanently modified.  For
-example:
-
-  (let ((-compare-fn #\\='=))
-    (-union \\='(1 2 3) \\='(2 3 4)))")
-
-(defun dash--member-fn ()
-  "Return the flavor of `member' that goes best with `-compare-fn'."
-  (declare (side-effect-free error-free))
-  (let ((cmp -compare-fn))
-    (cond ((memq cmp '(nil equal)) #'member)
-          ((eq cmp #'eq) #'memq)
-          ((eq cmp #'eql) #'memql)
-          ((lambda (elt list)
-             (while (and list (not (funcall cmp elt (car list))))
-               (pop list))
-             list)))))
-
-(defun dash--assoc-fn ()
-  "Return the flavor of `assoc' that goes best with `-compare-fn'."
-  (declare (side-effect-free error-free))
-  (let ((cmp -compare-fn))
-    (cond ((memq cmp '(nil equal)) #'assoc)
-          ((eq cmp #'eq) #'assq)
-          ;; Since Emacs 26, `assoc' accepts a custom `testfn'.
-          ;; Version testing would be simpler here, but feature
-          ;; testing gets more brownie points, I guess.
-          ((condition-case nil
-               (with-no-warnings (assoc nil () #'eql))
-             (wrong-number-of-arguments t))
-           (lambda (key alist)
-             (--first (and (consp it) (funcall cmp (car it) key)) alist)))
-          ((with-no-warnings
-             (lambda (key alist)
-               (assoc key alist cmp)))))))
-
-(defun dash--hash-test-fn ()
-  "Return the hash table test function corresponding to `-compare-fn'.
-Return nil if `-compare-fn' is not a known test function."
-  (declare (side-effect-free error-free))
-  ;; In theory this could also recognize values that are custom
-  ;; `hash-table-test's, but too often the :test name is different
-  ;; from the equality function, so it doesn't seem worthwhile.
-  (car (memq (or -compare-fn #'equal) '(equal eq eql))))
-
-(defvar dash--short-list-length 32
-  "Maximum list length considered short, for optimizations.
-For example, the speedup afforded by hash table lookup may start
-to outweigh its runtime and memory overhead for problem sizes
-greater than this value.  See also the discussion in PR #305.")
-
-(defun -distinct (list)
-  "Return a copy of LIST with all duplicate elements removed.
-
-The test for equality is done with `equal', or with `-compare-fn'
-if that is non-nil.
-
-Alias: `-uniq'."
-  (declare (important-return-value t))
-  (let (test len)
-    (cond ((null list) ())
-          ;; Use a hash table if `-compare-fn' is a known hash table
-          ;; test function and the list is long enough.
-          ((and (setq test (dash--hash-test-fn))
-                (> (setq len (length list)) dash--short-list-length))
-           (let ((ht (make-hash-table :test test :size len)))
-             (--filter (unless (gethash it ht) (puthash it t ht)) list)))
-          ((let ((member (dash--member-fn)) uniq)
-             (--each list (unless (funcall member it uniq) (push it uniq)))
-             (nreverse uniq))))))
-
-(defalias '-uniq #'-distinct)
-
-(defun dash--size+ (size1 size2)
-  "Return the sum of nonnegative fixnums SIZE1 and SIZE2.
-Return `most-positive-fixnum' on overflow.  This ensures the
-result is a valid size, particularly for allocating hash tables,
-even in the presence of bignum support."
-  (declare (side-effect-free t))
-  (if (< size1 (- most-positive-fixnum size2))
-      (+ size1 size2)
-    most-positive-fixnum))
-
-(defun -union (list1 list2)
-  "Return a new list of distinct elements appearing in either LIST1 or LIST2.
-
-The test for equality is done with `equal', or with `-compare-fn'
-if that is non-nil."
-  (declare (important-return-value t))
-  (let ((lists (list list1 list2)) test len union)
-    (cond ((null (or list1 list2)))
-          ;; Use a hash table if `-compare-fn' is a known hash table
-          ;; test function and the lists are long enough.
-          ((and (setq test (dash--hash-test-fn))
-                (> (setq len (dash--size+ (length list1) (length list2)))
-                   dash--short-list-length))
-           (let ((ht (make-hash-table :test test :size len)))
-             (dolist (l lists)
-               (--each l (unless (gethash it ht)
-                           (puthash it t ht)
-                           (push it union))))))
-          ((let ((member (dash--member-fn)))
-             (dolist (l lists)
-               (--each l (unless (funcall member it union) (push it union)))))))
-    (nreverse union)))
-
-(defun -intersection (list1 list2)
-  "Return a new list of distinct elements appearing in both LIST1 and LIST2.
-
-The test for equality is done with `equal', or with `-compare-fn'
-if that is non-nil."
-  (declare (important-return-value t))
-  (let (test len)
-    (cond ((null (and list1 list2)) ())
-          ;; Use a hash table if `-compare-fn' is a known hash table
-          ;; test function and either list is long enough.
-          ((and (setq test (dash--hash-test-fn))
-                (> (setq len (length list2)) dash--short-list-length))
-           (let ((ht (make-hash-table :test test :size len)))
-             (--each list2 (puthash it t ht))
-             ;; Remove visited elements to avoid duplicates.
-             (--filter (when (gethash it ht) (remhash it ht) t) list1)))
-          ((let ((member (dash--member-fn)) intersection)
-             (--each list1 (and (funcall member it list2)
-                                (not (funcall member it intersection))
-                                (push it intersection)))
-             (nreverse intersection))))))
-
-(defun -difference (list1 list2)
-  "Return a new list with the distinct members of LIST1 that are not in LIST2.
-
-The test for equality is done with `equal', or with `-compare-fn'
-if that is non-nil."
-  (declare (important-return-value t))
-  (let (test len1 len2)
-    (cond ((null list1) ())
-          ((null list2) (-distinct list1))
-          ;; Use a hash table if `-compare-fn' is a known hash table
-          ;; test function and the subtrahend is long enough.
-          ((and (setq test (dash--hash-test-fn))
-                (setq len1 (length list1))
-                (setq len2 (length list2))
-                (> (max len1 len2) dash--short-list-length))
-           (let ((ht1 (make-hash-table :test test :size len1))
-                 (ht2 (make-hash-table :test test :size len2)))
-             (--each list2 (puthash it t ht2))
-             ;; Avoid duplicates by tracking visited items in `ht1'.
-             (--filter (unless (or (gethash it ht2) (gethash it ht1))
-                         (puthash it t ht1))
-                       list1)))
-          ((let ((member (dash--member-fn)) difference)
-             (--each list1
-               (unless (or (funcall member it list2)
-                           (funcall member it difference))
-                 (push it difference)))
-             (nreverse difference))))))
-
-(defun -powerset (list)
-  "Return the power set of LIST."
-  (declare (pure t) (side-effect-free t))
-  (if (null list) (list ())
-    (let ((last (-powerset (cdr list))))
-      (nconc (mapcar (lambda (x) (cons (car list) x)) last)
-             last))))
-
-(defun -frequencies (list)
-  "Count the occurrences of each distinct element of LIST.
-
-Return an alist of (ELEMENT . N), where each ELEMENT occurs N
-times in LIST.
-
-The test for equality is done with `equal', or with `-compare-fn'
-if that is non-nil.
-
-See also `-count' and `-group-by'."
-  (declare (important-return-value t))
-  (let (test len freqs)
-    (cond ((null list))
-          ((and (setq test (dash--hash-test-fn))
-                (> (setq len (length list)) dash--short-list-length))
-           (let ((ht (make-hash-table :test test :size len)))
-             ;; Share structure between hash table and returned list.
-             ;; This affords a single pass that preserves the input
-             ;; order, conses less garbage, and is faster than a
-             ;; second traversal (e.g., with `maphash').
-             (--each list
-               (let ((freq (gethash it ht)))
-                 (if freq
-                     (setcdr freq (1+ (cdr freq)))
-                   (push (puthash it (cons it 1) ht) freqs))))))
-          ((let ((assoc (dash--assoc-fn)))
-             (--each list
-               (let ((freq (funcall assoc it freqs)))
-                 (if freq
-                     (setcdr freq (1+ (cdr freq)))
-                   (push (cons it 1) freqs)))))))
-    (nreverse freqs)))
-
-(defun dash--numbers<= (nums)
-  "Return non-nil if NUMS is a list of non-decreasing numbers."
-  (declare (pure t) (side-effect-free t))
-  (or (null nums)
-      (let ((prev (pop nums)))
-        (and (numberp prev)
-             (--every (and (numberp it) (<= prev (setq prev it))) nums)))))
-
-(defun dash--next-lex-perm (array n)
-  "Update ARRAY of N numbers with its next lexicographic permutation.
-Return nil if there is no such successor.  N should be nonzero.
-
-This implements the salient steps of Algorithm L (Lexicographic
-permutation generation) as described in DE Knuth's The Art of
-Computer Programming, Volume 4A / Combinatorial Algorithms,
-Part I, Addison-Wesley, 2011, § 7.2.1.2, p. 319."
-  (setq n (1- n))
-  (let* ((l n)
-         (j (1- n))
-         (al (aref array n))
-         (aj al))
-    ;; L2. [Find j].
-    ;; Decrement j until a[j] < a[j+1].
-    (while (and (<= 0 j)
-                (<= aj (setq aj (aref array j))))
-      (setq j (1- j)))
-    ;; Terminate algorithm if j not found.
-    (when (>= j 0)
-      ;; L3. [Increase a[j]].
-      ;; Decrement l until a[j] < a[l].
-      (while (>= aj al)
-        (setq l (1- l) al (aref array l)))
-      ;; Swap a[j] and a[l].
-      (aset array j al)
-      (aset array l aj)
-      ;; L4. [Reverse a[j+1]...a[n]].
-      (setq l n)
-      (while (< (setq j (1+ j)) l)
-        (setq aj (aref array j))
-        (aset array j (aref array l))
-        (aset array l aj)
-        (setq l (1- l)))
-      array)))
-
-(defun dash--lex-perms (vec &optional original)
-  "Return a list of permutations of VEC in lexicographic order.
-Specifically, return only the successors of VEC in lexicographic
-order.  Each returned permutation is a list.  VEC should comprise
-one or more numbers, and may be destructively modified.
-
-If ORIGINAL is a vector, then VEC is interpreted as a set of
-indices into ORIGINAL.  In this case, the indices are permuted,
-and the resulting index permutations are used to dereference
-elements of ORIGINAL."
-  (let ((len (length vec)) perms)
-    (while vec
-      (push (if original
-                (--map (aref original it) vec)
-              (append vec ()))
-            perms)
-      (setq vec (dash--next-lex-perm vec len)))
-    (nreverse perms)))
-
-(defun dash--uniq-perms (list)
-  "Return a list of permutations of LIST.
-LIST is treated as if all its elements are distinct."
-  (let* ((vec (vconcat list))
-         (idxs (copy-sequence vec)))
-    ;; Just construct a vector of the list's indices and permute that.
-    (dotimes (i (length idxs))
-      (aset idxs i i))
-    (dash--lex-perms idxs vec)))
-
-(defun dash--multi-perms (list freqs)
-  "Return a list of permutations of the multiset LIST.
-FREQS should be an alist describing the frequency of each element
-in LIST, as returned by `-frequencies'."
-  (let (;; Distinct items in `list', aka the cars of `freqs'.
-        (uniq (make-vector (length freqs) nil))
-        ;; Indices into `uniq'.
-        (idxs (make-vector (length list) nil))
-        ;; Current index into `idxs'.
-        (i 0))
-    (--each freqs
-      (aset uniq it-index (car it))
-      ;; Populate `idxs' with as many copies of each `it-index' as
-      ;; there are corresponding duplicates.
-      (dotimes (_ (cdr it))
-        (aset idxs i it-index)
-        (setq i (1+ i))))
-    (dash--lex-perms idxs uniq)))
-
-(defun -permutations (list)
-  "Return the distinct permutations of LIST.
-
-Duplicate elements of LIST are determined by `equal', or by
-`-compare-fn' if that is non-nil."
-  (declare (important-return-value t))
-  (cond ((null list) (list ()))
-        ;; Optimization: a traversal of `list' is faster than the
-        ;; round trip via `dash--uniq-perms' or `dash--multi-perms'.
-        ((dash--numbers<= list)
-         (dash--lex-perms (vconcat list)))
-        ((let ((freqs (-frequencies list)))
-           ;; Is each element distinct?
-           (unless (--every (= (cdr it) 1) freqs)
-             (dash--multi-perms list freqs))))
-        ((dash--uniq-perms list))))
-
-(defun -inits (list)
-  "Return all prefixes of LIST."
-  (declare (pure t) (side-effect-free t))
-  (let ((res (list list)))
-    (setq list (reverse list))
-    (while list
-      (push (reverse (!cdr list)) res))
-    res))
-
-(defun -tails (list)
-  "Return all suffixes of LIST."
-  (declare (pure t) (side-effect-free t))
-  (-reductions-r-from #'cons nil list))
-
-(defun -common-prefix (&rest lists)
-  "Return the longest common prefix of LISTS."
-  (declare (pure t) (side-effect-free t))
-  (--reduce (--take-while (and acc (equal (pop acc) it)) it)
-            lists))
-
-(defun -common-suffix (&rest lists)
-  "Return the longest common suffix of LISTS."
-  (declare (pure t) (side-effect-free t))
-  (nreverse (apply #'-common-prefix (mapcar #'reverse lists))))
-
-(defun -contains? (list element)
-  "Return non-nil if LIST contains ELEMENT.
-
-The test for equality is done with `equal', or with `-compare-fn'
-if that is non-nil.  As with `member', the return value is
-actually the tail of LIST whose car is ELEMENT.
-
-Alias: `-contains-p'."
-  (declare (important-return-value t))
-  (funcall (dash--member-fn) element list))
-
-(defalias '-contains-p #'-contains?)
-
-(defun -same-items? (list1 list2)
-  "Return non-nil if LIST1 and LIST2 have the same distinct elements.
-
-The order of the elements in the lists does not matter.  The
-lists may be of different lengths, i.e., contain duplicate
-elements.  The test for equality is done with `equal', or with
-`-compare-fn' if that is non-nil.
-
-Alias: `-same-items-p'."
-  (declare (important-return-value t))
-  (let (test len1 len2)
-    (cond ((null (or list1 list2)))
-          ((null (and list1 list2)) nil)
-          ;; Use a hash table if `-compare-fn' is a known hash table
-          ;; test function and either list is long enough.
-          ((and (setq test (dash--hash-test-fn))
-                (setq len1 (length list1))
-                (setq len2 (length list2))
-                (> (max len1 len2) dash--short-list-length))
-           (let ((ht1 (make-hash-table :test test :size len1))
-                 (ht2 (make-hash-table :test test :size len2)))
-             (--each list1 (puthash it t ht1))
-             ;; Move visited elements from `ht1' to `ht2'.  This way,
-             ;; if visiting all of `list2' leaves `ht1' empty, then
-             ;; all elements from both lists have been accounted for.
-             (and (--every (cond ((gethash it ht1)
-                                  (remhash it ht1)
-                                  (puthash it t ht2))
-                                 ((gethash it ht2)))
-                           list2)
-                  (zerop (hash-table-count ht1)))))
-          ((let ((member (dash--member-fn)))
-             (and (--all? (funcall member it list2) list1)
-                  (--all? (funcall member it list1) list2)))))))
-
-(defalias '-same-items-p #'-same-items?)
-
-(defun -is-prefix? (prefix list)
-  "Return non-nil if PREFIX is a prefix of LIST.
-
-Alias: `-is-prefix-p'."
-  (declare (pure t) (side-effect-free t))
-  (--each-while list (and (equal (car prefix) it)
-                          (!cdr prefix)))
-  (null prefix))
-
-(defun -is-suffix? (suffix list)
-  "Return non-nil if SUFFIX is a suffix of LIST.
-
-Alias: `-is-suffix-p'."
-  (declare (pure t) (side-effect-free t))
-  (equal suffix (last list (length suffix))))
-
-(defun -is-infix? (infix list)
-  "Return non-nil if INFIX is infix of LIST.
-
-This operation runs in O(n^2) time
-
-Alias: `-is-infix-p'"
-  (declare (pure t) (side-effect-free t))
-  (let (done)
-    (while (and (not done) list)
-      (setq done (-is-prefix? infix list))
-      (!cdr list))
-    done))
-
-(defalias '-is-prefix-p '-is-prefix?)
-(defalias '-is-suffix-p '-is-suffix?)
-(defalias '-is-infix-p '-is-infix?)
-
-(defun -sort (comparator list)
-  "Sort LIST, stably, comparing elements using COMPARATOR.
-Return the sorted list.  LIST is NOT modified by side effects.
-COMPARATOR is called with two elements of LIST, and should return non-nil
-if the first element should sort before the second."
-  (declare (important-return-value t))
-  ;; Not yet worth changing to (sort list :lessp comparator);
-  ;; still seems as fast or slightly faster.
-  (sort (copy-sequence list) comparator))
-
-(defmacro --sort (form list)
-  "Anaphoric form of `-sort'."
-  (declare (debug (def-form form)))
-  `(-sort (lambda (it other) (ignore it other) ,form) ,list))
-
-(defun -list (&optional arg &rest args)
-  "Ensure ARG is a list.
-If ARG is already a list, return it as is (not a copy).
-Otherwise, return a new list with ARG as its only element.
-
-Another supported calling convention is (-list &rest ARGS).
-In this case, if ARG is not a list, a new list with all of
-ARGS as elements is returned.  This use is supported for
-backward compatibility and is otherwise deprecated."
-  (declare (advertised-calling-convention (arg) "2.18.0")
-           (pure t) (side-effect-free error-free))
-  (if (listp arg) arg (cons arg args)))
-
-(defun -repeat (n x)
-  "Return a new list of length N with each element being X.
-Return nil if N is less than 1."
-  (declare (side-effect-free t))
-  (and (>= n 0) (make-list n x)))
-
-(defun -sum (list)
-  "Return the sum of LIST."
-  (declare (pure t) (side-effect-free t))
-  (apply #'+ list))
-
-(defun -running-sum (list)
-  "Return a list with running sums of items in LIST.
-LIST must be non-empty."
-  (declare (pure t) (side-effect-free t))
-  (or list (signal 'wrong-type-argument (list #'consp list)))
-  (-reductions #'+ list))
-
-(defun -product (list)
-  "Return the product of LIST."
-  (declare (pure t) (side-effect-free t))
-  (apply #'* list))
-
-(defun -running-product (list)
-  "Return a list with running products of items in LIST.
-LIST must be non-empty."
-  (declare (pure t) (side-effect-free t))
-  (or list (signal 'wrong-type-argument (list #'consp list)))
-  (-reductions #'* list))
-
-(defun -max (list)
-  "Return the largest value from LIST of numbers or markers."
-  (declare (pure t) (side-effect-free t))
-  (apply #'max list))
-
-(defun -min (list)
-  "Return the smallest value from LIST of numbers or markers."
-  (declare (pure t) (side-effect-free t))
-  (apply #'min list))
-
-(defun -max-by (comparator list)
-  "Take a comparison function COMPARATOR and a LIST and return
-the greatest element of the list by the comparison function.
-
-See also combinator `-on' which can transform the values before
-comparing them."
-  (declare (important-return-value t))
-  (--reduce (if (funcall comparator it acc) it acc) list))
-
-(defun -min-by (comparator list)
-  "Take a comparison function COMPARATOR and a LIST and return
-the least element of the list by the comparison function.
-
-See also combinator `-on' which can transform the values before
-comparing them."
-  (declare (important-return-value t))
-  (--reduce (if (funcall comparator it acc) acc it) list))
-
-(defmacro --max-by (form list)
-  "Anaphoric version of `-max-by'.
-
-The items for the comparator form are exposed as \"it\" and \"other\"."
-  (declare (debug (def-form form)))
-  `(-max-by (lambda (it other) (ignore it other) ,form) ,list))
-
-(defmacro --min-by (form list)
-  "Anaphoric version of `-min-by'.
-
-The items for the comparator form are exposed as \"it\" and \"other\"."
-  (declare (debug (def-form form)))
-  `(-min-by (lambda (it other) (ignore it other) ,form) ,list))
-
-(defun -iota (count &optional start step)
-  "Return a list containing COUNT numbers.
-Starts from START and adds STEP each time.  The default START is
-zero, the default STEP is 1.
-This function takes its name from the corresponding primitive in
-the APL language."
-  (declare (side-effect-free t))
-  (unless (natnump count)
-    (signal 'wrong-type-argument (list #'natnump count)))
-  (or start (setq start 0))
-  (or step (setq step 1))
-  (if (zerop step)
-      (make-list count start)
-    (--iterate (+ it step) start count)))
-
-(defun -fix (fn list)
-  "Compute the (least) fixpoint of FN with initial input LIST.
-
-FN is called at least once, results are compared with `equal'."
-  (declare (important-return-value t))
-  (let ((re (funcall fn list)))
-    (while (not (equal list re))
-      (setq list re)
-      (setq re (funcall fn re)))
-    re))
-
-(defmacro --fix (form list)
-  "Anaphoric form of `-fix'."
-  (declare (debug (def-form form)))
-  `(-fix (lambda (it) (ignore it) ,form) ,list))
-
-(defun -unfold (fun seed)
-  "Build a list from SEED using FUN.
-
-This is \"dual\" operation to `-reduce-r': while -reduce-r
-consumes a list to produce a single value, `-unfold' takes a
-seed value and builds a (potentially infinite!) list.
-
-FUN should return nil to stop the generating process, or a
-cons (A . B), where A will be prepended to the result and B is
-the new seed."
-  (declare (important-return-value t))
-  (let ((last (funcall fun seed)) r)
-    (while last
-      (push (car last) r)
-      (setq last (funcall fun (cdr last))))
-    (nreverse r)))
-
-(defmacro --unfold (form seed)
-  "Anaphoric version of `-unfold'."
-  (declare (debug (def-form form)))
-  `(-unfold (lambda (it) (ignore it) ,form) ,seed))
-
-(defun -cons-pair? (obj)
-  "Return non-nil if OBJ is a true cons pair.
-That is, a cons (A . B) where B is not a list.
-
-Alias: `-cons-pair-p'."
-  (declare (pure t) (side-effect-free error-free))
-  (nlistp (cdr-safe obj)))
-
-(defalias '-cons-pair-p '-cons-pair?)
-
-(defun -cons-to-list (con)
-  "Convert a cons pair to a list with `car' and `cdr' of the pair respectively."
-  (declare (pure t) (side-effect-free t))
-  (list (car con) (cdr con)))
-
-(defun -value-to-list (val)
-  "Convert a value to a list.
-
-If the value is a cons pair, make a list with two elements, `car'
-and `cdr' of the pair respectively.
-
-If the value is anything else, wrap it in a list."
-  (declare (pure t) (side-effect-free t))
-  (if (-cons-pair? val) (-cons-to-list val) (list val)))
-
-(defun -tree-mapreduce-from (fn folder init-value tree)
-  "Apply FN to each element of TREE, and make a list of the results.
-If elements of TREE are lists themselves, apply FN recursively to
-elements of these nested lists.
-
-Then reduce the resulting lists using FOLDER and initial value
-INIT-VALUE. See `-reduce-r-from'.
-
-This is the same as calling `-tree-reduce-from' after `-tree-map'
-but is twice as fast as it only traverse the structure once."
-  (declare (important-return-value t))
-  (cond
-   ((null tree) ())
-   ((-cons-pair? tree) (funcall fn tree))
-   ((consp tree)
-    (-reduce-r-from
-     folder init-value
-     (mapcar (lambda (x) (-tree-mapreduce-from fn folder init-value x)) tree)))
-   ((funcall fn tree))))
-
-(defmacro --tree-mapreduce-from (form folder init-value tree)
-  "Anaphoric form of `-tree-mapreduce-from'."
-  (declare (debug (def-form def-form form form)))
-  `(-tree-mapreduce-from (lambda (it) (ignore it) ,form)
-                         (lambda (it acc) (ignore it acc) ,folder)
-                         ,init-value
-                         ,tree))
-
-(defun -tree-mapreduce (fn folder tree)
-  "Apply FN to each element of TREE, and make a list of the results.
-If elements of TREE are lists themselves, apply FN recursively to
-elements of these nested lists.
-
-Then reduce the resulting lists using FOLDER and initial value
-INIT-VALUE. See `-reduce-r-from'.
-
-This is the same as calling `-tree-reduce' after `-tree-map'
-but is twice as fast as it only traverse the structure once."
-  (declare (important-return-value t))
-  (cond
-   ((null tree) ())
-   ((-cons-pair? tree) (funcall fn tree))
-   ((consp tree)
-    (-reduce-r folder (mapcar (lambda (x) (-tree-mapreduce fn folder x)) tree)))
-   ((funcall fn tree))))
-
-(defmacro --tree-mapreduce (form folder tree)
-  "Anaphoric form of `-tree-mapreduce'."
-  (declare (debug (def-form def-form form)))
-  `(-tree-mapreduce (lambda (it) (ignore it) ,form)
-                    (lambda (it acc) (ignore it acc) ,folder)
-                    ,tree))
-
-(defun -tree-map (fn tree)
-  "Apply FN to each element of TREE while preserving the tree structure."
-  (declare (important-return-value t))
-  (cond
-   ((null tree) ())
-   ((-cons-pair? tree) (funcall fn tree))
-   ((consp tree)
-    (mapcar (lambda (x) (-tree-map fn x)) tree))
-   ((funcall fn tree))))
-
-(defmacro --tree-map (form tree)
-  "Anaphoric form of `-tree-map'."
-  (declare (debug (def-form form)))
-  `(-tree-map (lambda (it) (ignore it) ,form) ,tree))
-
-(defun -tree-reduce-from (fn init-value tree)
-  "Use FN to reduce elements of list TREE.
-If elements of TREE are lists themselves, apply the reduction recursively.
-
-FN is first applied to INIT-VALUE and first element of the list,
-then on this result and second element from the list etc.
-
-The initial value is ignored on cons pairs as they always contain
-two elements."
-  (declare (important-return-value t))
-  (cond
-   ((null tree) ())
-   ((-cons-pair? tree) tree)
-   ((consp tree)
-    (-reduce-r-from
-     fn init-value
-     (mapcar (lambda (x) (-tree-reduce-from fn init-value x)) tree)))
-   (tree)))
-
-(defmacro --tree-reduce-from (form init-value tree)
-  "Anaphoric form of `-tree-reduce-from'."
-  (declare (debug (def-form form form)))
-  `(-tree-reduce-from (lambda (it acc) (ignore it acc) ,form)
-                      ,init-value ,tree))
-
-(defun -tree-reduce (fn tree)
-  "Use FN to reduce elements of list TREE.
-If elements of TREE are lists themselves, apply the reduction recursively.
-
-FN is first applied to first element of the list and second
-element, then on this result and third element from the list etc.
-
-See `-reduce-r' for how exactly are lists of zero or one element handled."
-  (declare (important-return-value t))
-  (cond
-   ((null tree) ())
-   ((-cons-pair? tree) tree)
-   ((consp tree)
-    (-reduce-r fn (mapcar (lambda (x) (-tree-reduce fn x)) tree)))
-   (tree)))
-
-(defmacro --tree-reduce (form tree)
-  "Anaphoric form of `-tree-reduce'."
-  (declare (debug (def-form form)))
-  `(-tree-reduce (lambda (it acc) (ignore it acc) ,form) ,tree))
-
-(defun -tree-map-nodes (pred fun tree)
-  "Call FUN on each node of TREE that satisfies PRED.
-
-If PRED returns nil, continue descending down this node.  If PRED
-returns non-nil, apply FUN to this node and do not descend
-further."
-  (cond ((funcall pred tree) (funcall fun tree))
-        ((and (listp tree) (listp (cdr tree)))
-         (-map (lambda (x) (-tree-map-nodes pred fun x)) tree))
-        (tree)))
-
-(defmacro --tree-map-nodes (pred form tree)
-  "Anaphoric form of `-tree-map-nodes'."
-  (declare (debug (def-form def-form form)))
-  `(-tree-map-nodes (lambda (it) (ignore it) ,pred)
-                    (lambda (it) (ignore it) ,form)
-                    ,tree))
-
-(defun -tree-seq (branch children tree)
-  "Return a sequence of the nodes in TREE, in depth-first search order.
-
-BRANCH is a predicate of one argument that returns non-nil if the
-passed argument is a branch, that is, a node that can have children.
-
-CHILDREN is a function of one argument that returns the children
-of the passed branch node.
-
-Non-branch nodes are simply copied."
-  (declare (important-return-value t))
-  (cons tree
-        (and (funcall branch tree)
-             (-mapcat (lambda (x) (-tree-seq branch children x))
-                      (funcall children tree)))))
-
-(defmacro --tree-seq (branch children tree)
-  "Anaphoric form of `-tree-seq'."
-  (declare (debug (def-form def-form form)))
-  `(-tree-seq (lambda (it) (ignore it) ,branch)
-              (lambda (it) (ignore it) ,children)
-              ,tree))
-
-(defun -clone (list)
-  "Create a deep copy of LIST.
-The new list has the same elements and structure but all cons are
-replaced with new ones.  This is useful when you need to clone a
-structure such as plist or alist."
-  (declare (side-effect-free t))
-  (-tree-map #'identity list))
-\f
-;;; Combinators
-
-(defalias '-partial #'apply-partially)
-
-(defun -rpartial (fn &rest args)
-  "Return a function that is a partial application of FN to ARGS.
-ARGS is a list of the last N arguments to pass to FN.  The result
-is a new function which does the same as FN, except that the last
-N arguments are fixed at the values with which this function was
-called.  This is like `-partial', except the arguments are fixed
-starting from the right rather than the left."
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (&rest args-before) (apply fn (append args-before args))))
-
-(defun -juxt (&rest fns)
-  "Return a function that is the juxtaposition of FNS.
-The returned function takes a variable number of ARGS, applies
-each of FNS in turn to ARGS, and returns the list of results."
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (&rest args) (mapcar (lambda (x) (apply x args)) fns)))
-
-(defun -compose (&rest fns)
-  "Compose FNS into a single composite function.
-Return a function that takes a variable number of ARGS, applies
-the last function in FNS to ARGS, and returns the result of
-calling each remaining function on the result of the previous
-function, right-to-left.  If no FNS are given, return a variadic
-`identity' function."
-  (declare (pure t) (side-effect-free error-free))
-  (let* ((fns (nreverse fns))
-         (head (car fns))
-         (tail (cdr fns)))
-    (cond (tail
-           (lambda (&rest args)
-             (--reduce-from (funcall it acc) (apply head args) tail)))
-          (fns head)
-          ((lambda (&optional arg &rest _) arg)))))
-
-(defun -applify (fn)
-  "Return a function that applies FN to a single list of args.
-This changes the arity of FN from taking N distinct arguments to
-taking 1 argument which is a list of N arguments."
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (args) (apply fn args)))
-
-(defun -on (op trans)
-  "Return a function that calls TRANS on each arg and OP on the results.
-The returned function takes a variable number of arguments, calls
-the function TRANS on each one in turn, and then passes those
-results as the list of arguments to OP, in the same order.
-
-For example, the following pairs of expressions are morally
-equivalent:
-
-  (funcall (-on #\\='+ #\\='1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
-  (funcall (-on #\\='+ #\\='1+))       = (+)"
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (&rest args)
-    ;; This unrolling seems to be a relatively cheap way to keep the
-    ;; overhead of `mapcar' + `apply' in check.
-    (cond ((cddr args)
-           (apply op (mapcar trans args)))
-          ((cdr args)
-           (funcall op (funcall trans (car args)) (funcall trans (cadr args))))
-          (args
-           (funcall op (funcall trans (car args))))
-          ((funcall op)))))
-
-(defun -flip (fn)
-  "Return a function that calls FN with its arguments reversed.
-The returned function takes the same number of arguments as FN.
-
-For example, the following two expressions are morally
-equivalent:
-
-  (funcall (-flip #\\='-) 1 2) = (- 2 1)
-
-See also: `-rotate-args'."
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (&rest args) ;; Open-code for speed.
-    (cond ((cddr args) (apply fn (nreverse args)))
-          ((cdr args) (funcall fn (cadr args) (car args)))
-          (args (funcall fn (car args)))
-          ((funcall fn)))))
-
-(defun -rotate-args (n fn)
-  "Return a function that calls FN with args rotated N places to the right.
-The returned function takes the same number of arguments as FN,
-rotates the list of arguments N places to the right (left if N is
-negative) just like `-rotate', and applies FN to the result.
-
-See also: `-flip'."
-  (declare (pure t) (side-effect-free t))
-  (if (zerop n)
-      fn
-    (let ((even (= (% n 2) 0)))
-      (lambda (&rest args)
-        (cond ((cddr args) ;; Open-code for speed.
-               (apply fn (-rotate n args)))
-              ((cdr args)
-               (let ((fst (car args))
-                     (snd (cadr args)))
-                 (funcall fn (if even fst snd) (if even snd fst))))
-              (args
-               (funcall fn (car args)))
-              ((funcall fn)))))))
-
-(defun -const (c)
-  "Return a function that returns C ignoring any additional arguments.
-
-In types: a -> b -> a"
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (&rest _) c))
-
-(defmacro -cut (&rest params)
-  "Take n-ary function and n arguments and specialize some of them.
-Arguments denoted by <> will be left unspecialized.
-
-See SRFI-26 for detailed description."
-  (declare (debug (&optional sexp &rest &or "<>" form)))
-  (let* ((i 0)
-         (args (--keep (when (eq it '<>)
-                         (setq i (1+ i))
-                         (make-symbol (format "D%d" i)))
-                       params)))
-    `(lambda ,args
-       ,(let ((body (--map (if (eq it '<>) (pop args) it) params)))
-          (if (eq (car params) '<>)
-              (cons #'funcall body)
-            body)))))
-
-(defun -not (pred)
-  "Return a predicate that negates the result of PRED.
-The returned predicate passes its arguments to PRED.  If PRED
-returns nil, the result is non-nil; otherwise the result is nil.
-
-See also: `-andfn' and `-orfn'."
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (&rest args) (not (apply pred args))))
-
-(defun -orfn (&rest preds)
-  "Return a predicate that returns the first non-nil result of PREDS.
-The returned predicate takes a variable number of arguments,
-passes them to each predicate in PREDS in turn until one of them
-returns non-nil, and returns that non-nil result without calling
-the remaining PREDS.  If all PREDS return nil, or if no PREDS are
-given, the returned predicate returns nil.
-
-See also: `-andfn' and `-not'."
-  (declare (pure t) (side-effect-free error-free))
-  ;; Open-code for speed.
-  (cond ((cdr preds) (lambda (&rest args) (--some (apply it args) preds)))
-        (preds (car preds))
-        (#'ignore)))
-
-(defun -andfn (&rest preds)
-  "Return a predicate that returns non-nil if all PREDS do so.
-The returned predicate P takes a variable number of arguments and
-passes them to each predicate in PREDS in turn.  If any one of
-PREDS returns nil, P also returns nil without calling the
-remaining PREDS.  If all PREDS return non-nil, P returns the last
-such value.  If no PREDS are given, P always returns non-nil.
-
-See also: `-orfn' and `-not'."
-  (declare (pure t) (side-effect-free error-free))
-  ;; Open-code for speed.
-  (cond ((cdr preds) (lambda (&rest args) (--every (apply it args) preds)))
-        (preds (car preds))
-        ;; As a `pure' function, this runtime check may generate
-        ;; backward-incompatible bytecode for `(-andfn)' at compile-time,
-        ;; but I doubt that's a problem in practice (famous last words).
-        ((fboundp 'always) #'always)
-        ((lambda (&rest _) t))))
-
-(defun -iteratefn (fn n)
-  "Return a function FN composed N times with itself.
-
-FN is a unary function.  If you need to use a function of higher
-arity, use `-applify' first to turn it into a unary function.
-
-With n = 0, this acts as identity function.
-
-In types: (a -> a) -> Int -> a -> a.
-
-This function satisfies the following law:
-
-  (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n)))."
-  (declare (pure t) (side-effect-free error-free))
-  (lambda (x) (--dotimes n (setq x (funcall fn x))) x))
-
-(defun -counter (&optional beg end inc)
-  "Return a closure that counts from BEG to END, with increment INC.
-
-The closure will return the next value in the counting sequence
-each time it is called, and nil after END is reached. BEG
-defaults to 0, INC defaults to 1, and if END is nil, the counter
-will increment indefinitely.
-
-The closure accepts any number of arguments, which are discarded."
-  (declare (pure t) (side-effect-free error-free))
-  (let ((inc (or inc 1))
-        (n (or beg 0)))
-    (lambda (&rest _)
-      (when (or (not end) (< n end))
-        (prog1 n
-          (setq n (+ n inc)))))))
-
-(defvar -fixfn-max-iterations 1000
-  "The default maximum number of iterations performed by `-fixfn'
-  unless otherwise specified.")
-
-(defun -fixfn (fn &optional equal-test halt-test)
-  "Return a function that computes the (least) fixpoint of FN.
-
-FN must be a unary function. The returned lambda takes a single
-argument, X, the initial value for the fixpoint iteration. The
-iteration halts when either of the following conditions is satisfied:
-
- 1. Iteration converges to the fixpoint, with equality being
-    tested using EQUAL-TEST. If EQUAL-TEST is not specified,
-    `equal' is used. For functions over the floating point
-    numbers, it may be necessary to provide an appropriate
-    approximate comparison test.
-
- 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a
-    simple counter that returns t after `-fixfn-max-iterations',
-    to guard against infinite iteration. Otherwise, HALT-TEST
-    must be a function that accepts a single argument, the
-    current value of X, and returns non-nil as long as iteration
-    should continue. In this way, a more sophisticated
-    convergence test may be supplied by the caller.
-
-The return value of the lambda is either the fixpoint or, if
-iteration halted before converging, a cons with car `halted' and
-cdr the final output from HALT-TEST.
-
-In types: (a -> a) -> a -> a."
-  (declare (important-return-value t))
-  (let ((eqfn   (or equal-test 'equal))
-        (haltfn (or halt-test
-                    (-not
-                     (-counter 0 -fixfn-max-iterations)))))
-    (lambda (x)
-      (let ((re (funcall fn x))
-            (halt? (funcall haltfn x)))
-        (while (and (not halt?) (not (funcall eqfn x re)))
-          (setq x     re
-                re    (funcall fn re)
-                halt? (funcall haltfn re)))
-        (if halt? (cons 'halted halt?)
-          re)))))
-
-(defun -prodfn (&rest fns)
-  "Return a function that applies each of FNS to each of a list of arguments.
-
-Takes a list of N functions and returns a function that takes a
-list of length N, applying Ith function to Ith element of the
-input list.  Returns a list of length N.
-
-In types (for N=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d)
-
-This function satisfies the following laws:
-
-    (-compose (-prodfn f g ...)
-              (-prodfn f\\=' g\\=' ...))
-  = (-prodfn (-compose f f\\=')
-             (-compose g g\\=')
-             ...)
-
-    (-prodfn f g ...)
-  = (-juxt (-compose f (-partial #\\='nth 0))
-           (-compose g (-partial #\\='nth 1))
-           ...)
-
-    (-compose (-prodfn f g ...)
-              (-juxt f\\=' g\\=' ...))
-  = (-juxt (-compose f f\\=')
-           (-compose g g\\=')
-           ...)
-
-    (-compose (-partial #\\='nth n)
-              (-prod f1 f2 ...))
-  = (-compose fn (-partial #\\='nth n))"
-  (declare (pure t) (side-effect-free t))
-  (lambda (x) (--zip-with (funcall it other) fns x)))
-\f
-;;; Font lock
-
-(defvar dash--keywords
-  `(;; TODO: Do not fontify the following automatic variables
-    ;; globally; detect and limit to their local anaphoric scope.
-    (,(rx symbol-start (| "acc" "it" "it-index" "other") symbol-end)
-     0 font-lock-variable-name-face)
-    ;; Macros in dev/examples.el.  Based on `lisp-mode-symbol-regexp'.
-    (,(rx ?\( (group (| "defexamples" "def-example-group")) symbol-end
-          (+ (in "\t "))
-          (group (* (| (syntax word) (syntax symbol) (: ?\\ nonl)))))
-     (1 font-lock-keyword-face)
-     (2 font-lock-function-name-face))
-    ;; Symbols in dev/examples.el.
-    ,(rx symbol-start (| "=>" "~>" "!!>") symbol-end)
-    ;; Elisp macro fontification was static prior to Emacs 25.
-    ,@(when (< emacs-major-version 25)
-        (let ((macs '("!cdr"
-                      "!cons"
-                      "-->"
-                      "--all-p"
-                      "--all?"
-                      "--annotate"
-                      "--any"
-                      "--any-p"
-                      "--any?"
-                      "--count"
-                      "--dotimes"
-                      "--doto"
-                      "--drop-while"
-                      "--each"
-                      "--each-indexed"
-                      "--each-r"
-                      "--each-r-while"
-                      "--each-while"
-                      "--every"
-                      "--every-p"
-                      "--every?"
-                      "--filter"
-                      "--find"
-                      "--find-index"
-                      "--find-indices"
-                      "--find-last-index"
-                      "--first"
-                      "--fix"
-                      "--group-by"
-                      "--if-let"
-                      "--iterate"
-                      "--keep"
-                      "--last"
-                      "--map"
-                      "--map-first"
-                      "--map-indexed"
-                      "--map-last"
-                      "--map-when"
-                      "--mapcat"
-                      "--max-by"
-                      "--min-by"
-                      "--none-p"
-                      "--none?"
-                      "--only-some-p"
-                      "--only-some?"
-                      "--partition-after-pred"
-                      "--partition-by"
-                      "--partition-by-header"
-                      "--reduce"
-                      "--reduce-from"
-                      "--reduce-r"
-                      "--reduce-r-from"
-                      "--reductions"
-                      "--reductions-from"
-                      "--reductions-r"
-                      "--reductions-r-from"
-                      "--reject"
-                      "--reject-first"
-                      "--reject-last"
-                      "--remove"
-                      "--remove-first"
-                      "--remove-last"
-                      "--replace-where"
-                      "--select"
-                      "--separate"
-                      "--some"
-                      "--some-p"
-                      "--some?"
-                      "--sort"
-                      "--splice"
-                      "--splice-list"
-                      "--split-when"
-                      "--split-with"
-                      "--take-while"
-                      "--tree-map"
-                      "--tree-map-nodes"
-                      "--tree-mapreduce"
-                      "--tree-mapreduce-from"
-                      "--tree-reduce"
-                      "--tree-reduce-from"
-                      "--tree-seq"
-                      "--unfold"
-                      "--update-at"
-                      "--when-let"
-                      "--zip-with"
-                      "->"
-                      "->>"
-                      "-as->"
-                      "-cut"
-                      "-doto"
-                      "-if-let"
-                      "-if-let*"
-                      "-lambda"
-                      "-let"
-                      "-let*"
-                      "-setq"
-                      "-some-->"
-                      "-some->"
-                      "-some->>"
-                      "-split-on"
-                      "-when-let"
-                      "-when-let*")))
-          `((,(concat "(" (regexp-opt macs 'symbols)) . 1)))))
-  "Font lock keywords for `dash-fontify-mode'.")
-
-(defcustom dash-fontify-mode-lighter nil
-  "Mode line lighter for `dash-fontify-mode'.
-Either a string to display in the mode line when
-`dash-fontify-mode' is on, or nil to display
-nothing (the default)."
-  :package-version '(dash . "2.18.0")
-  :type '(choice (string :tag "Lighter" :value " Dash")
-                 (const :tag "Nothing" nil)))
-
-;;;###autoload
-(define-minor-mode dash-fontify-mode
-  "Toggle fontification of Dash special variables.
-
-Dash-Fontify mode is a buffer-local minor mode intended for Emacs
-Lisp buffers.  Enabling it causes the special variables bound in
-anaphoric Dash macros to be fontified.  These anaphoras include
-`it', `it-index', `acc', and `other'.  In older Emacs versions
-which do not dynamically detect macros, Dash-Fontify mode
-additionally fontifies Dash macro calls.
-
-See also `dash-fontify-mode-lighter' and
-`global-dash-fontify-mode'."
-  :lighter dash-fontify-mode-lighter
-  (if dash-fontify-mode
-      (font-lock-add-keywords nil dash--keywords t)
-    (font-lock-remove-keywords nil dash--keywords))
-  (cond ((fboundp 'font-lock-flush) ;; Added in Emacs 25.
-         (font-lock-flush))
-        ;; `font-lock-fontify-buffer' unconditionally enables
-        ;; `font-lock-mode' and is marked `interactive-only' in later
-        ;; Emacs versions which have `font-lock-flush', so we guard
-        ;; and pacify as needed, respectively.
-        (font-lock-mode
-         (with-no-warnings
-           (font-lock-fontify-buffer)))))
-
-(defun dash--turn-on-fontify-mode ()
-  "Enable `dash-fontify-mode' if in an Emacs Lisp buffer."
-  (when (derived-mode-p #'emacs-lisp-mode)
-    (dash-fontify-mode)))
-
-;;;###autoload
-(define-globalized-minor-mode global-dash-fontify-mode
-  dash-fontify-mode dash--turn-on-fontify-mode)
-
-(defcustom dash-enable-fontlock nil
-  "If non-nil, fontify Dash macro calls and special variables."
-  :set (lambda (sym val)
-         (set-default sym val)
-         (global-dash-fontify-mode (if val 1 0)))
-  :type 'boolean)
-
-(make-obsolete-variable
- 'dash-enable-fontlock #'global-dash-fontify-mode "2.18.0")
-
-(define-obsolete-function-alias
-  'dash-enable-font-lock #'global-dash-fontify-mode "2.18.0")
-\f
-;;; Info
-
-(defvar dash--info-doc-spec '("(dash) Index" nil "^ -+ .*: " "\\( \\|$\\)")
-  "The Dash :doc-spec entry for `info-lookup-alist'.
-It is based on that for `emacs-lisp-mode'.")
-
-(defun dash--info-elisp-docs ()
-  "Return the `emacs-lisp-mode' symbol docs from `info-lookup-alist'.
-Specifically, return the cons containing their
-`info-lookup->doc-spec' so that we can modify it."
-  (defvar info-lookup-alist)
-  (nthcdr 3 (assq #'emacs-lisp-mode (cdr (assq 'symbol info-lookup-alist)))))
-
-;;;###autoload
-(defun dash-register-info-lookup ()
-  "Register the Dash Info manual with `info-lookup-symbol'.
-This allows Dash symbols to be looked up with \\[info-lookup-symbol]."
-  (interactive)
-  (require 'info-look)
-  (let ((docs (dash--info-elisp-docs)))
-    (setcar docs (append (car docs) (list dash--info-doc-spec)))
-    (info-lookup-reset)))
-
-(defun dash-unload-function ()
-  "Remove Dash from `info-lookup-alist'.
-Used by `unload-feature', which see."
-  (let ((docs (and (featurep 'info-look)
-                   (dash--info-elisp-docs))))
-    (when (member dash--info-doc-spec (car docs))
-      (setcar docs (remove dash--info-doc-spec (car docs)))
-      (info-lookup-reset)))
-  nil)
-
-(provide 'dash)
-;;; dash.el ends here
diff --git a/elpa/dash-20240510.1327/dash.info b/elpa/dash-20240510.1327/dash.info
deleted file mode 100644 (file)
index 4a66021..0000000
+++ /dev/null
@@ -1,4948 +0,0 @@
-This is dash.info, produced by makeinfo version 6.7 from dash.texi.
-
-This manual is for Dash version 2.19.1.
-
-   Copyright © 2012–2024 Free Software Foundation, Inc.
-
-     Permission is granted to copy, distribute and/or modify this
-     document under the terms of the GNU Free Documentation License,
-     Version 1.3 or any later version published by the Free Software
-     Foundation; with the Invariant Sections being “GNU General Public
-     License,” and no Front-Cover Texts or Back-Cover Texts.  A copy of
-     the license is included in the section entitled “GNU Free
-     Documentation License”.
-INFO-DIR-SECTION Emacs
-START-INFO-DIR-ENTRY
-* Dash: (dash.info).    A modern list library for GNU Emacs.
-END-INFO-DIR-ENTRY
-
-\1f
-File: dash.info,  Node: Top,  Next: Installation,  Up: (dir)
-
-Dash
-****
-
-This manual is for Dash version 2.19.1.
-
-   Copyright © 2012–2024 Free Software Foundation, Inc.
-
-     Permission is granted to copy, distribute and/or modify this
-     document under the terms of the GNU Free Documentation License,
-     Version 1.3 or any later version published by the Free Software
-     Foundation; with the Invariant Sections being “GNU General Public
-     License,” and no Front-Cover Texts or Back-Cover Texts.  A copy of
-     the license is included in the section entitled “GNU Free
-     Documentation License”.
-
-* Menu:
-
-* Installation::        Installing and configuring Dash.
-* Functions::           Dash API reference.
-* Development::         Contributing to Dash development.
-
-Appendices
-
-* FDL::                 The license for this documentation.
-* GPL::                 Conditions for copying and changing Dash.
-* Index::               Index including functions and macros.
-
- — The Detailed Node Listing —
-
-Installation
-
-* Using in a package::  Listing Dash as a package dependency.
-* Fontification of special variables::  Font Lock of anaphoric macro variables.
-* Info symbol lookup::  Looking up Dash symbols in this manual.
-
-Functions
-
-* Maps::
-* Sublist selection::
-* List to list::
-* Reductions::
-* Unfolding::
-* Predicates::
-* Partitioning::
-* Indexing::
-* Set operations::
-* Other list operations::
-* Tree operations::
-* Threading macros::
-* Binding::
-* Side effects::
-* Destructive operations::
-* Function combinators::
-
-Development
-
-* Contribute::          How to contribute.
-* Contributors::        List of contributors.
-
-\1f
-File: dash.info,  Node: Installation,  Next: Functions,  Prev: Top,  Up: Top
-
-1 Installation
-**************
-
-Dash is available on GNU ELPA (https://elpa.gnu.org/), GNU-devel ELPA
-(https://elpa.gnu.org/devel/), and MELPA (https://melpa.org/), and can
-be installed with the standard command ‘package-install’ (*note
-(emacs)Package Installation::).
-
-‘M-x package-install <RET> dash <RET>’
-     Install the Dash library.
-
-   Alternatively, you can just dump ‘dash.el’ in your ‘load-path’
-somewhere (*note (emacs)Lisp Libraries::).
-
-* Menu:
-
-* Using in a package::  Listing Dash as a package dependency.
-* Fontification of special variables::  Font Lock of anaphoric macro variables.
-* Info symbol lookup::  Looking up Dash symbols in this manual.
-
-\1f
-File: dash.info,  Node: Using in a package,  Next: Fontification of special variables,  Up: Installation
-
-1.1 Using in a package
-======================
-
-If you use Dash in your own package, be sure to list it as a dependency
-in the library’s headers as follows (*note (elisp)Library Headers::).
-
-     ;; Package-Requires: ((dash "2.19.1"))
-
-\1f
-File: dash.info,  Node: Fontification of special variables,  Next: Info symbol lookup,  Prev: Using in a package,  Up: Installation
-
-1.2 Fontification of special variables
-======================================
-
-The autoloaded minor mode ‘dash-fontify-mode’ is provided for optional
-fontification of anaphoric Dash variables (‘it’, ‘acc’, etc.) in Emacs
-Lisp buffers using search-based Font Lock (*note (emacs)Font Lock::).
-In older Emacs versions which do not dynamically detect macros, the
-minor mode also fontifies calls to Dash macros.
-
-   To automatically enable the minor mode in all Emacs Lisp buffers,
-just call its autoloaded global counterpart ‘global-dash-fontify-mode’,
-either interactively or from your ‘user-init-file’:
-
-     (global-dash-fontify-mode)
-
-\1f
-File: dash.info,  Node: Info symbol lookup,  Prev: Fontification of special variables,  Up: Installation
-
-1.3 Info symbol lookup
-======================
-
-While editing Elisp files, you can use ‘C-h S’ (‘info-lookup-symbol’) to
-look up Elisp symbols in the relevant Info manuals (*note (emacs)Info
-Lookup::).  To enable the same for Dash symbols, use the command
-‘dash-register-info-lookup’.  It can be called directly when needed, or
-automatically from your ‘user-init-file’.  For example:
-
-     (with-eval-after-load 'info-look
-       (dash-register-info-lookup))
-
-\1f
-File: dash.info,  Node: Functions,  Next: Development,  Prev: Installation,  Up: Top
-
-2 Functions
-***********
-
-This chapter contains reference documentation for the Dash API
-(Application Programming Interface).  The names of all public functions
-defined in the library are prefixed with a dash character (‘-’).
-
-   The library also provides anaphoric macro versions of functions where
-that makes sense.  The names of these macros are prefixed with two
-dashes (‘--’) instead of one.
-
-   For instance, while the function ‘-map’ applies a function to each
-element of a list, its anaphoric counterpart ‘--map’ evaluates a form
-with the local variable ‘it’ temporarily bound to the current list
-element instead.
-
-     ;; Normal version.
-     (-map (lambda (n) (* n n)) '(1 2 3 4))
-         ⇒ (1 4 9 16)
-
-     ;; Anaphoric version.
-     (--map (* it it) '(1 2 3 4))
-         ⇒ (1 4 9 16)
-
-   The normal version can, of course, also be written as in the
-following example, which demonstrates the utility of both versions.
-
-     (defun my-square (n)
-       "Return N multiplied by itself."
-       (* n n))
-
-     (-map #'my-square '(1 2 3 4))
-         ⇒ (1 4 9 16)
-
-* Menu:
-
-* Maps::
-* Sublist selection::
-* List to list::
-* Reductions::
-* Unfolding::
-* Predicates::
-* Partitioning::
-* Indexing::
-* Set operations::
-* Other list operations::
-* Tree operations::
-* Threading macros::
-* Binding::
-* Side effects::
-* Destructive operations::
-* Function combinators::
-
-\1f
-File: dash.info,  Node: Maps,  Next: Sublist selection,  Up: Functions
-
-2.1 Maps
-========
-
-Functions in this category take a transforming function, which is then
-applied sequentially to each or selected elements of the input list.
-The results are collected in order and returned as a new list.
-
- -- Function: -map (fn list)
-     Apply FN to each item in LIST and return the list of results.
-
-     This function’s anaphoric counterpart is ‘--map’.
-
-          (-map (lambda (num) (* num num)) '(1 2 3 4))
-              ⇒ (1 4 9 16)
-          (-map #'1+ '(1 2 3 4))
-              ⇒ (2 3 4 5)
-          (--map (* it it) '(1 2 3 4))
-              ⇒ (1 4 9 16)
-
- -- Function: -map-when (pred rep list)
-     Use PRED to conditionally apply REP to each item in LIST.  Return a
-     copy of LIST where the items for which PRED returns ‘nil’ are
-     unchanged, and the rest are mapped through the REP function.
-
-     Alias: ‘-replace-where’
-
-     See also: ‘-update-at’ (*note -update-at::)
-
-          (-map-when 'even? 'square '(1 2 3 4))
-              ⇒ (1 4 3 16)
-          (--map-when (> it 2) (* it it) '(1 2 3 4))
-              ⇒ (1 2 9 16)
-          (--map-when (= it 2) 17 '(1 2 3 4))
-              ⇒ (1 17 3 4)
-
- -- Function: -map-first (pred rep list)
-     Use PRED to determine the first item in LIST to call REP on.
-     Return a copy of LIST where the first item for which PRED returns
-     non-‘nil’ is replaced with the result of calling REP on that item.
-
-     See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note
-     -replace-first::)
-
-          (-map-first 'even? 'square '(1 2 3 4))
-              ⇒ (1 4 3 4)
-          (--map-first (> it 2) (* it it) '(1 2 3 4))
-              ⇒ (1 2 9 4)
-          (--map-first (= it 2) 17 '(1 2 3 2))
-              ⇒ (1 17 3 2)
-
- -- Function: -map-last (pred rep list)
-     Use PRED to determine the last item in LIST to call REP on.  Return
-     a copy of LIST where the last item for which PRED returns non-‘nil’
-     is replaced with the result of calling REP on that item.
-
-     See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note
-     -replace-last::)
-
-          (-map-last 'even? 'square '(1 2 3 4))
-              ⇒ (1 2 3 16)
-          (--map-last (> it 2) (* it it) '(1 2 3 4))
-              ⇒ (1 2 3 16)
-          (--map-last (= it 2) 17 '(1 2 3 2))
-              ⇒ (1 2 3 17)
-
- -- Function: -map-indexed (fn list)
-     Apply FN to each index and item in LIST and return the list of
-     results.  This is like ‘-map’ (*note -map::), but FN takes two
-     arguments: the index of the current element within LIST, and the
-     element itself.
-
-     This function’s anaphoric counterpart is ‘--map-indexed’.
-
-     For a side-effecting variant, see also ‘-each-indexed’ (*note
-     -each-indexed::).
-
-          (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4))
-              ⇒ (1 1 1 1)
-          (--map-indexed (- it it-index) '(1 2 3 4))
-              ⇒ (1 1 1 1)
-          (-map-indexed #'* '(1 2 3 4))
-              ⇒ (0 2 6 12)
-
- -- Function: -annotate (fn list)
-     Pair each item in LIST with the result of passing it to FN.
-
-     Return an alist of (RESULT .  ITEM), where each ITEM is the
-     corresponding element of LIST, and RESULT is the value obtained by
-     calling FN on ITEM.
-
-     This function’s anaphoric counterpart is ‘--annotate’.
-
-          (-annotate #'1+ '(1 2 3))
-              ⇒ ((2 . 1) (3 . 2) (4 . 3))
-          (-annotate #'length '((f o o) (bar baz)))
-              ⇒ ((3 f o o) (2 bar baz))
-          (--annotate (> it 1) '(0 1 2 3))
-              ⇒ ((nil . 0) (nil . 1) (t . 2) (t . 3))
-
- -- Function: -splice (pred fun list)
-     Splice lists generated by FUN in place of items satisfying PRED in
-     LIST.
-
-     Call PRED on each element of LIST.  Whenever the result of PRED is
-     ‘nil’, leave that ‘it’ as-is.  Otherwise, call FUN on the same ‘it’
-     that satisfied PRED.  The result should be a (possibly empty) list
-     of items to splice in place of ‘it’ in LIST.
-
-     This can be useful as an alternative to the ‘,@’ construct in a ‘`’
-     structure, in case you need to splice several lists at marked
-     positions (for example with keywords).
-
-     This function’s anaphoric counterpart is ‘--splice’.
-
-     See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’
-     (*note -insert-at::).
-
-          (-splice #'numberp (lambda (n) (list n n)) '(a 1 b 2))
-              ⇒ (a 1 1 b 2 2)
-          (--splice t (list it it) '(1 2 3 4))
-              ⇒ (1 1 2 2 3 3 4 4)
-          (--splice (eq it :magic) '((magical) (code)) '((foo) :magic (bar)))
-              ⇒ ((foo) (magical) (code) (bar))
-
- -- Function: -splice-list (pred new-list list)
-     Splice NEW-LIST in place of elements matching PRED in LIST.
-
-     See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note
-     -insert-at::)
-
-          (-splice-list 'keywordp '(a b c) '(1 :foo 2))
-              ⇒ (1 a b c 2)
-          (-splice-list 'keywordp nil '(1 :foo 2))
-              ⇒ (1 2)
-          (--splice-list (keywordp it) '(a b c) '(1 :foo 2))
-              ⇒ (1 a b c 2)
-
- -- Function: -mapcat (fn list)
-     Return the concatenation of the result of mapping FN over LIST.
-     Thus function FN should return a list.
-
-          (-mapcat 'list '(1 2 3))
-              ⇒ (1 2 3)
-          (-mapcat (lambda (item) (list 0 item)) '(1 2 3))
-              ⇒ (0 1 0 2 0 3)
-          (--mapcat (list 0 it) '(1 2 3))
-              ⇒ (0 1 0 2 0 3)
-
- -- Function: -copy (list)
-     Create a shallow copy of LIST.
-
-          (-copy '(1 2 3))
-              ⇒ (1 2 3)
-          (let ((a '(1 2 3))) (eq a (-copy a)))
-              ⇒ nil
-
-\1f
-File: dash.info,  Node: Sublist selection,  Next: List to list,  Prev: Maps,  Up: Functions
-
-2.2 Sublist selection
-=====================
-
-Functions returning a sublist of the original list.
-
- -- Function: -filter (pred list)
-     Return a new list of the items in LIST for which PRED returns
-     non-‘nil’.
-
-     Alias: ‘-select’.
-
-     This function’s anaphoric counterpart is ‘--filter’.
-
-     For similar operations, see also ‘-keep’ (*note -keep::) and
-     ‘-remove’ (*note -remove::).
-
-          (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4))
-              ⇒ (2 4)
-          (-filter #'natnump '(-2 -1 0 1 2))
-              ⇒ (0 1 2)
-          (--filter (= 0 (% it 2)) '(1 2 3 4))
-              ⇒ (2 4)
-
- -- Function: -remove (pred list)
-     Return a new list of the items in LIST for which PRED returns
-     ‘nil’.
-
-     Alias: ‘-reject’.
-
-     This function’s anaphoric counterpart is ‘--remove’.
-
-     For similar operations, see also ‘-keep’ (*note -keep::) and
-     ‘-filter’ (*note -filter::).
-
-          (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4))
-              ⇒ (1 3)
-          (-remove #'natnump '(-2 -1 0 1 2))
-              ⇒ (-2 -1)
-          (--remove (= 0 (% it 2)) '(1 2 3 4))
-              ⇒ (1 3)
-
- -- Function: -remove-first (pred list)
-     Remove the first item from LIST for which PRED returns non-‘nil’.
-     This is a non-destructive operation, but only the front of LIST
-     leading up to the removed item is a copy; the rest is LIST’s
-     original tail.  If no item is removed, then the result is a
-     complete copy.
-
-     Alias: ‘-reject-first’.
-
-     This function’s anaphoric counterpart is ‘--remove-first’.
-
-     See also ‘-map-first’ (*note -map-first::), ‘-remove-item’ (*note
-     -remove-item::), and ‘-remove-last’ (*note -remove-last::).
-
-          (-remove-first #'natnump '(-2 -1 0 1 2))
-              ⇒ (-2 -1 1 2)
-          (-remove-first #'stringp '(1 2 "first" "second"))
-              ⇒ (1 2 "second")
-          (--remove-first (> it 3) '(1 2 3 4 5 6))
-              ⇒ (1 2 3 5 6)
-
- -- Function: -remove-last (pred list)
-     Remove the last item from LIST for which PRED returns non-‘nil’.
-     The result is a copy of LIST regardless of whether an element is
-     removed.
-
-     Alias: ‘-reject-last’.
-
-     This function’s anaphoric counterpart is ‘--remove-last’.
-
-     See also ‘-map-last’ (*note -map-last::), ‘-remove-item’ (*note
-     -remove-item::), and ‘-remove-first’ (*note -remove-first::).
-
-          (-remove-last #'natnump '(1 3 5 4 7 8 10 -11))
-              ⇒ (1 3 5 4 7 8 -11)
-          (-remove-last #'stringp '(1 2 "last" "second"))
-              ⇒ (1 2 "last")
-          (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10))
-              ⇒ (1 2 3 4 5 6 7 8 9)
-
- -- Function: -remove-item (item list)
-     Return a copy of LIST with all occurrences of ITEM removed.  The
-     comparison is done with ‘equal’.
-
-          (-remove-item 3 '(1 2 3 2 3 4 5 3))
-              ⇒ (1 2 2 4 5)
-          (-remove-item 'foo '(foo bar baz foo))
-              ⇒ (bar baz)
-          (-remove-item "bob" '("alice" "bob" "eve" "bob"))
-              ⇒ ("alice" "eve")
-
- -- Function: -non-nil (list)
-     Return a copy of LIST with all ‘nil’ items removed.
-
-          (-non-nil '(nil 1 nil 2 nil nil 3 4 nil 5 nil))
-              ⇒ (1 2 3 4 5)
-          (-non-nil '((nil)))
-              ⇒ ((nil))
-          (-non-nil ())
-              ⇒ ()
-
- -- Function: -slice (list from &optional to step)
-     Return copy of LIST, starting from index FROM to index TO.
-
-     FROM or TO may be negative.  These values are then interpreted
-     modulo the length of the list.
-
-     If STEP is a number, only each STEPth item in the resulting section
-     is returned.  Defaults to 1.
-
-          (-slice '(1 2 3 4 5) 1)
-              ⇒ (2 3 4 5)
-          (-slice '(1 2 3 4 5) 0 3)
-              ⇒ (1 2 3)
-          (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2)
-              ⇒ (2 4 6 8)
-
- -- Function: -take (n list)
-     Return a copy of the first N items in LIST.  Return a copy of LIST
-     if it contains N items or fewer.  Return ‘nil’ if N is zero or
-     less.
-
-     See also: ‘-take-last’ (*note -take-last::).
-
-          (-take 3 '(1 2 3 4 5))
-              ⇒ (1 2 3)
-          (-take 17 '(1 2 3 4 5))
-              ⇒ (1 2 3 4 5)
-          (-take 0 '(1 2 3 4 5))
-              ⇒ ()
-
- -- Function: -take-last (n list)
-     Return a copy of the last N items of LIST in order.  Return a copy
-     of LIST if it contains N items or fewer.  Return ‘nil’ if N is zero
-     or less.
-
-     See also: ‘-take’ (*note -take::).
-
-          (-take-last 3 '(1 2 3 4 5))
-              ⇒ (3 4 5)
-          (-take-last 17 '(1 2 3 4 5))
-              ⇒ (1 2 3 4 5)
-          (-take-last 1 '(1 2 3 4 5))
-              ⇒ (5)
-
- -- Function: -drop (n list)
-     Return the tail (not a copy) of LIST without the first N items.
-     Return ‘nil’ if LIST contains N items or fewer.  Return LIST if N
-     is zero or less.
-
-     For another variant, see also ‘-drop-last’ (*note -drop-last::).
-
-          (-drop 3 '(1 2 3 4 5))
-              ⇒ (4 5)
-          (-drop 17 '(1 2 3 4 5))
-              ⇒ ()
-          (-drop 0 '(1 2 3 4 5))
-              ⇒ (1 2 3 4 5)
-
- -- Function: -drop-last (n list)
-     Return a copy of LIST without its last N items.  Return a copy of
-     LIST if N is zero or less.  Return ‘nil’ if LIST contains N items
-     or fewer.
-
-     See also: ‘-drop’ (*note -drop::).
-
-          (-drop-last 3 '(1 2 3 4 5))
-              ⇒ (1 2)
-          (-drop-last 17 '(1 2 3 4 5))
-              ⇒ ()
-          (-drop-last 0 '(1 2 3 4 5))
-              ⇒ (1 2 3 4 5)
-
- -- Function: -take-while (pred list)
-     Take successive items from LIST for which PRED returns non-‘nil’.
-     PRED is a function of one argument.  Return a new list of the
-     successive elements from the start of LIST for which PRED returns
-     non-‘nil’.
-
-     This function’s anaphoric counterpart is ‘--take-while’.
-
-     For another variant, see also ‘-drop-while’ (*note -drop-while::).
-
-          (-take-while #'even? '(1 2 3 4))
-              ⇒ ()
-          (-take-while #'even? '(2 4 5 6))
-              ⇒ (2 4)
-          (--take-while (< it 4) '(1 2 3 4 3 2 1))
-              ⇒ (1 2 3)
-
- -- Function: -drop-while (pred list)
-     Drop successive items from LIST for which PRED returns non-‘nil’.
-     PRED is a function of one argument.  Return the tail (not a copy)
-     of LIST starting from its first element for which PRED returns
-     ‘nil’.
-
-     This function’s anaphoric counterpart is ‘--drop-while’.
-
-     For another variant, see also ‘-take-while’ (*note -take-while::).
-
-          (-drop-while #'even? '(1 2 3 4))
-              ⇒ (1 2 3 4)
-          (-drop-while #'even? '(2 4 5 6))
-              ⇒ (5 6)
-          (--drop-while (< it 4) '(1 2 3 4 3 2 1))
-              ⇒ (4 3 2 1)
-
- -- Function: -select-by-indices (indices list)
-     Return a list whose elements are elements from LIST selected as
-     ‘(nth i list)‘ for all i from INDICES.
-
-          (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r"))
-              ⇒ ("c" "o" "l" "o" "r")
-          (-select-by-indices '(2 1 0) '("a" "b" "c"))
-              ⇒ ("c" "b" "a")
-          (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l"))
-              ⇒ ("f" "a" "r" "f" "a" "l" "l" "a")
-
- -- Function: -select-columns (columns table)
-     Select COLUMNS from TABLE.
-
-     TABLE is a list of lists where each element represents one row.  It
-     is assumed each row has the same length.
-
-     Each row is transformed such that only the specified COLUMNS are
-     selected.
-
-     See also: ‘-select-column’ (*note -select-column::),
-     ‘-select-by-indices’ (*note -select-by-indices::)
-
-          (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c)))
-              ⇒ ((1 3) (a c) (:a :c))
-          (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c)))
-              ⇒ ((2) (b) (:b))
-          (-select-columns nil '((1 2 3) (a b c) (:a :b :c)))
-              ⇒ (nil nil nil)
-
- -- Function: -select-column (column table)
-     Select COLUMN from TABLE.
-
-     TABLE is a list of lists where each element represents one row.  It
-     is assumed each row has the same length.
-
-     The single selected column is returned as a list.
-
-     See also: ‘-select-columns’ (*note -select-columns::),
-     ‘-select-by-indices’ (*note -select-by-indices::)
-
-          (-select-column 1 '((1 2 3) (a b c) (:a :b :c)))
-              ⇒ (2 b :b)
-
-\1f
-File: dash.info,  Node: List to list,  Next: Reductions,  Prev: Sublist selection,  Up: Functions
-
-2.3 List to list
-================
-
-Functions returning a modified copy of the input list.
-
- -- Function: -keep (fn list)
-     Return a new list of the non-‘nil’ results of applying FN to each
-     item in LIST.  Like ‘-filter’ (*note -filter::), but returns the
-     non-‘nil’ results of FN instead of the corresponding elements of
-     LIST.
-
-     Its anaphoric counterpart is ‘--keep’.
-
-          (-keep #'cdr '((1 2 3) (4 5) (6)))
-              ⇒ ((2 3) (5))
-          (-keep (lambda (n) (and (> n 3) (* 10 n))) '(1 2 3 4 5 6))
-              ⇒ (40 50 60)
-          (--keep (and (> it 3) (* 10 it)) '(1 2 3 4 5 6))
-              ⇒ (40 50 60)
-
- -- Function: -concat (&rest sequences)
-     Concatenate all the arguments and make the result a list.  The
-     result is a list whose elements are the elements of all the
-     arguments.  Each argument may be a list, vector or string.
-
-     All arguments except the last argument are copied.  The last
-     argument is just used as the tail of the new list.
-
-          (-concat '(1))
-              ⇒ (1)
-          (-concat '(1) '(2))
-              ⇒ (1 2)
-          (-concat '(1) '(2 3) '(4))
-              ⇒ (1 2 3 4)
-
- -- Function: -flatten (l)
-     Take a nested list L and return its contents as a single, flat
-     list.
-
-     Note that because ‘nil’ represents a list of zero elements (an
-     empty list), any mention of ‘nil’ in L will disappear after
-     flattening.  If you need to preserve nils, consider ‘-flatten-n’
-     (*note -flatten-n::) or map them to some unique symbol and then map
-     them back.
-
-     Conses of two atoms are considered "terminals", that is, they
-     aren’t flattened further.
-
-     See also: ‘-flatten-n’ (*note -flatten-n::)
-
-          (-flatten '((1)))
-              ⇒ (1)
-          (-flatten '((1 (2 3) (((4 (5)))))))
-              ⇒ (1 2 3 4 5)
-          (-flatten '(1 2 (3 . 4)))
-              ⇒ (1 2 (3 . 4))
-
- -- Function: -flatten-n (num list)
-     Flatten NUM levels of a nested LIST.
-
-     See also: ‘-flatten’ (*note -flatten::)
-
-          (-flatten-n 1 '((1 2) ((3 4) ((5 6)))))
-              ⇒ (1 2 (3 4) ((5 6)))
-          (-flatten-n 2 '((1 2) ((3 4) ((5 6)))))
-              ⇒ (1 2 3 4 (5 6))
-          (-flatten-n 3 '((1 2) ((3 4) ((5 6)))))
-              ⇒ (1 2 3 4 5 6)
-
- -- Function: -replace (old new list)
-     Replace all OLD items in LIST with NEW.
-
-     Elements are compared using ‘equal’.
-
-     See also: ‘-replace-at’ (*note -replace-at::)
-
-          (-replace 1 "1" '(1 2 3 4 3 2 1))
-              ⇒ ("1" 2 3 4 3 2 "1")
-          (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
-              ⇒ ("a" "nice" "bar" "sentence" "about" "bar")
-          (-replace 1 2 nil)
-              ⇒ nil
-
- -- Function: -replace-first (old new list)
-     Replace the first occurrence of OLD with NEW in LIST.
-
-     Elements are compared using ‘equal’.
-
-     See also: ‘-map-first’ (*note -map-first::)
-
-          (-replace-first 1 "1" '(1 2 3 4 3 2 1))
-              ⇒ ("1" 2 3 4 3 2 1)
-          (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
-              ⇒ ("a" "nice" "bar" "sentence" "about" "foo")
-          (-replace-first 1 2 nil)
-              ⇒ nil
-
- -- Function: -replace-last (old new list)
-     Replace the last occurrence of OLD with NEW in LIST.
-
-     Elements are compared using ‘equal’.
-
-     See also: ‘-map-last’ (*note -map-last::)
-
-          (-replace-last 1 "1" '(1 2 3 4 3 2 1))
-              ⇒ (1 2 3 4 3 2 "1")
-          (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
-              ⇒ ("a" "nice" "foo" "sentence" "about" "bar")
-          (-replace-last 1 2 nil)
-              ⇒ nil
-
- -- Function: -insert-at (n x list)
-     Return a list with X inserted into LIST at position N.
-
-     See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note
-     -splice-list::)
-
-          (-insert-at 1 'x '(a b c))
-              ⇒ (a x b c)
-          (-insert-at 12 'x '(a b c))
-              ⇒ (a b c x)
-
- -- Function: -replace-at (n x list)
-     Return a list with element at Nth position in LIST replaced with X.
-
-     See also: ‘-replace’ (*note -replace::)
-
-          (-replace-at 0 9 '(0 1 2 3 4 5))
-              ⇒ (9 1 2 3 4 5)
-          (-replace-at 1 9 '(0 1 2 3 4 5))
-              ⇒ (0 9 2 3 4 5)
-          (-replace-at 4 9 '(0 1 2 3 4 5))
-              ⇒ (0 1 2 3 9 5)
-
- -- Function: -update-at (n func list)
-     Use FUNC to update the Nth element of LIST.  Return a copy of LIST
-     where the Nth element is replaced with the result of calling FUNC
-     on it.
-
-     See also: ‘-map-when’ (*note -map-when::)
-
-          (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5))
-              ⇒ (9 1 2 3 4 5)
-          (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5))
-              ⇒ (0 9 2 3 4 5)
-          (--update-at 2 (length it) '("foo" "bar" "baz" "quux"))
-              ⇒ ("foo" "bar" 3 "quux")
-
- -- Function: -remove-at (n list)
-     Return LIST with its element at index N removed.  That is, remove
-     any element selected as (nth N LIST) from LIST and return the
-     result.
-
-     This is a non-destructive operation: parts of LIST (but not
-     necessarily all of it) are copied as needed to avoid destructively
-     modifying it.
-
-     See also: ‘-remove-at-indices’ (*note -remove-at-indices::),
-     ‘-remove’ (*note -remove::).
-
-          (-remove-at 0 '(a b c))
-              ⇒ (b c)
-          (-remove-at 1 '(a b c))
-              ⇒ (a c)
-          (-remove-at 2 '(a b c))
-              ⇒ (a b)
-
- -- Function: -remove-at-indices (indices list)
-     Return LIST with its elements at INDICES removed.  That is, for
-     each index I in INDICES, remove any element selected as (nth I
-     LIST) from LIST.
-
-     This is a non-destructive operation: parts of LIST (but not
-     necessarily all of it) are copied as needed to avoid destructively
-     modifying it.
-
-     See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note
-     -remove::).
-
-          (-remove-at-indices '(0) '(a b c d e))
-              ⇒ (b c d e)
-          (-remove-at-indices '(1 3) '(a b c d e))
-              ⇒ (a c e)
-          (-remove-at-indices '(4 0 2) '(a b c d e))
-              ⇒ (b d)
-
-\1f
-File: dash.info,  Node: Reductions,  Next: Unfolding,  Prev: List to list,  Up: Functions
-
-2.4 Reductions
-==============
-
-Functions reducing lists to a single value (which may also be a list).
-
- -- Function: -reduce-from (fn init list)
-     Reduce the function FN across LIST, starting with INIT.  Return the
-     result of applying FN to INIT and the first element of LIST, then
-     applying FN to that result and the second element, etc.  If LIST is
-     empty, return INIT without calling FN.
-
-     This function’s anaphoric counterpart is ‘--reduce-from’.
-
-     For other folds, see also ‘-reduce’ (*note -reduce::) and
-     ‘-reduce-r’ (*note -reduce-r::).
-
-          (-reduce-from #'- 10 '(1 2 3))
-              ⇒ 4
-          (-reduce-from #'list 10 '(1 2 3))
-              ⇒ (((10 1) 2) 3)
-          (--reduce-from (concat acc " " it) "START" '("a" "b" "c"))
-              ⇒ "START a b c"
-
- -- Function: -reduce-r-from (fn init list)
-     Reduce the function FN across LIST in reverse, starting with INIT.
-     Return the result of applying FN to the last element of LIST and
-     INIT, then applying FN to the second-to-last element and the
-     previous result of FN, etc.  That is, the first argument of FN is
-     the current element, and its second argument the accumulated value.
-     If LIST is empty, return INIT without calling FN.
-
-     This function is like ‘-reduce-from’ (*note -reduce-from::) but the
-     operation associates from the right rather than left.  In other
-     words, it starts from the end of LIST and flips the arguments to
-     FN.  Conceptually, it is like replacing the conses in LIST with
-     applications of FN, and its last link with INIT, and evaluating the
-     resulting expression.
-
-     This function’s anaphoric counterpart is ‘--reduce-r-from’.
-
-     For other folds, see also ‘-reduce-r’ (*note -reduce-r::) and
-     ‘-reduce’ (*note -reduce::).
-
-          (-reduce-r-from #'- 10 '(1 2 3))
-              ⇒ -8
-          (-reduce-r-from #'list 10 '(1 2 3))
-              ⇒ (1 (2 (3 10)))
-          (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c"))
-              ⇒ "a b c END"
-
- -- Function: -reduce (fn list)
-     Reduce the function FN across LIST.  Return the result of applying
-     FN to the first two elements of LIST, then applying FN to that
-     result and the third element, etc.  If LIST contains a single
-     element, return it without calling FN.  If LIST is empty, return
-     the result of calling FN with no arguments.
-
-     This function’s anaphoric counterpart is ‘--reduce’.
-
-     For other folds, see also ‘-reduce-from’ (*note -reduce-from::) and
-     ‘-reduce-r’ (*note -reduce-r::).
-
-          (-reduce #'- '(1 2 3 4))
-              ⇒ -8
-          (-reduce #'list '(1 2 3 4))
-              ⇒ (((1 2) 3) 4)
-          (--reduce (format "%s-%d" acc it) '(1 2 3))
-              ⇒ "1-2-3"
-
- -- Function: -reduce-r (fn list)
-     Reduce the function FN across LIST in reverse.  Return the result
-     of applying FN to the last two elements of LIST, then applying FN
-     to the third-to-last element and the previous result of FN, etc.
-     That is, the first argument of FN is the current element, and its
-     second argument the accumulated value.  If LIST contains a single
-     element, return it without calling FN.  If LIST is empty, return
-     the result of calling FN with no arguments.
-
-     This function is like ‘-reduce’ (*note -reduce::) but the operation
-     associates from the right rather than left.  In other words, it
-     starts from the end of LIST and flips the arguments to FN.
-     Conceptually, it is like replacing the conses in LIST with
-     applications of FN, ignoring its last link, and evaluating the
-     resulting expression.
-
-     This function’s anaphoric counterpart is ‘--reduce-r’.
-
-     For other folds, see also ‘-reduce-r-from’ (*note -reduce-r-from::)
-     and ‘-reduce’ (*note -reduce::).
-
-          (-reduce-r #'- '(1 2 3 4))
-              ⇒ -2
-          (-reduce-r #'list '(1 2 3 4))
-              ⇒ (1 (2 (3 4)))
-          (--reduce-r (format "%s-%d" acc it) '(1 2 3))
-              ⇒ "3-2-1"
-
- -- Function: -reductions-from (fn init list)
-     Return a list of FN’s intermediate reductions across LIST.  That
-     is, a list of the intermediate values of the accumulator when
-     ‘-reduce-from’ (*note -reduce-from::) (which see) is called with
-     the same arguments.
-
-     This function’s anaphoric counterpart is ‘--reductions-from’.
-
-     For other folds, see also ‘-reductions’ (*note -reductions::) and
-     ‘-reductions-r’ (*note -reductions-r::).
-
-          (-reductions-from #'max 0 '(2 1 4 3))
-              ⇒ (0 2 2 4 4)
-          (-reductions-from #'* 1 '(1 2 3 4))
-              ⇒ (1 1 2 6 24)
-          (--reductions-from (format "(FN %s %d)" acc it) "INIT" '(1 2 3))
-              ⇒ ("INIT" "(FN INIT 1)" "(FN (FN INIT 1) 2)" "(FN (FN (FN INIT 1) 2) 3)")
-
- -- Function: -reductions-r-from (fn init list)
-     Return a list of FN’s intermediate reductions across reversed LIST.
-     That is, a list of the intermediate values of the accumulator when
-     ‘-reduce-r-from’ (*note -reduce-r-from::) (which see) is called
-     with the same arguments.
-
-     This function’s anaphoric counterpart is ‘--reductions-r-from’.
-
-     For other folds, see also ‘-reductions’ (*note -reductions::) and
-     ‘-reductions-r’ (*note -reductions-r::).
-
-          (-reductions-r-from #'max 0 '(2 1 4 3))
-              ⇒ (4 4 4 3 0)
-          (-reductions-r-from #'* 1 '(1 2 3 4))
-              ⇒ (24 24 12 4 1)
-          (--reductions-r-from (format "(FN %d %s)" it acc) "INIT" '(1 2 3))
-              ⇒ ("(FN 1 (FN 2 (FN 3 INIT)))" "(FN 2 (FN 3 INIT))" "(FN 3 INIT)" "INIT")
-
- -- Function: -reductions (fn list)
-     Return a list of FN’s intermediate reductions across LIST.  That
-     is, a list of the intermediate values of the accumulator when
-     ‘-reduce’ (*note -reduce::) (which see) is called with the same
-     arguments.
-
-     This function’s anaphoric counterpart is ‘--reductions’.
-
-     For other folds, see also ‘-reductions’ (*note -reductions::) and
-     ‘-reductions-r’ (*note -reductions-r::).
-
-          (-reductions #'+ '(1 2 3 4))
-              ⇒ (1 3 6 10)
-          (-reductions #'* '(1 2 3 4))
-              ⇒ (1 2 6 24)
-          (--reductions (format "(FN %s %d)" acc it) '(1 2 3))
-              ⇒ (1 "(FN 1 2)" "(FN (FN 1 2) 3)")
-
- -- Function: -reductions-r (fn list)
-     Return a list of FN’s intermediate reductions across reversed LIST.
-     That is, a list of the intermediate values of the accumulator when
-     ‘-reduce-r’ (*note -reduce-r::) (which see) is called with the same
-     arguments.
-
-     This function’s anaphoric counterpart is ‘--reductions-r’.
-
-     For other folds, see also ‘-reductions-r-from’ (*note
-     -reductions-r-from::) and ‘-reductions’ (*note -reductions::).
-
-          (-reductions-r #'+ '(1 2 3 4))
-              ⇒ (10 9 7 4)
-          (-reductions-r #'* '(1 2 3 4))
-              ⇒ (24 24 12 4)
-          (--reductions-r (format "(FN %d %s)" it acc) '(1 2 3))
-              ⇒ ("(FN 1 (FN 2 3))" "(FN 2 3)" 3)
-
- -- Function: -count (pred list)
-     Counts the number of items in LIST where (PRED item) is non-‘nil’.
-
-          (-count 'even? '(1 2 3 4 5))
-              ⇒ 2
-          (--count (< it 4) '(1 2 3 4))
-              ⇒ 3
-
- -- Function: -sum (list)
-     Return the sum of LIST.
-
-          (-sum ())
-              ⇒ 0
-          (-sum '(1))
-              ⇒ 1
-          (-sum '(1 2 3 4))
-              ⇒ 10
-
- -- Function: -running-sum (list)
-     Return a list with running sums of items in LIST.  LIST must be
-     non-empty.
-
-          (-running-sum '(1 2 3 4))
-              ⇒ (1 3 6 10)
-          (-running-sum '(1))
-              ⇒ (1)
-          (-running-sum ())
-              error→ Wrong type argument: consp, nil
-
- -- Function: -product (list)
-     Return the product of LIST.
-
-          (-product ())
-              ⇒ 1
-          (-product '(1))
-              ⇒ 1
-          (-product '(1 2 3 4))
-              ⇒ 24
-
- -- Function: -running-product (list)
-     Return a list with running products of items in LIST.  LIST must be
-     non-empty.
-
-          (-running-product '(1 2 3 4))
-              ⇒ (1 2 6 24)
-          (-running-product '(1))
-              ⇒ (1)
-          (-running-product ())
-              error→ Wrong type argument: consp, nil
-
- -- Function: -inits (list)
-     Return all prefixes of LIST.
-
-          (-inits '(1 2 3 4))
-              ⇒ (nil (1) (1 2) (1 2 3) (1 2 3 4))
-          (-inits nil)
-              ⇒ (nil)
-          (-inits '(1))
-              ⇒ (nil (1))
-
- -- Function: -tails (list)
-     Return all suffixes of LIST.
-
-          (-tails '(1 2 3 4))
-              ⇒ ((1 2 3 4) (2 3 4) (3 4) (4) nil)
-          (-tails nil)
-              ⇒ (nil)
-          (-tails '(1))
-              ⇒ ((1) nil)
-
- -- Function: -common-prefix (&rest lists)
-     Return the longest common prefix of LISTS.
-
-          (-common-prefix '(1))
-              ⇒ (1)
-          (-common-prefix '(1 2) '(3 4) '(1 2))
-              ⇒ ()
-          (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4))
-              ⇒ (1 2)
-
- -- Function: -common-suffix (&rest lists)
-     Return the longest common suffix of LISTS.
-
-          (-common-suffix '(1))
-              ⇒ (1)
-          (-common-suffix '(1 2) '(3 4) '(1 2))
-              ⇒ ()
-          (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4))
-              ⇒ (3 4)
-
- -- Function: -min (list)
-     Return the smallest value from LIST of numbers or markers.
-
-          (-min '(0))
-              ⇒ 0
-          (-min '(3 2 1))
-              ⇒ 1
-          (-min '(1 2 3))
-              ⇒ 1
-
- -- Function: -min-by (comparator list)
-     Take a comparison function COMPARATOR and a LIST and return the
-     least element of the list by the comparison function.
-
-     See also combinator ‘-on’ (*note -on::) which can transform the
-     values before comparing them.
-
-          (-min-by '> '(4 3 6 1))
-              ⇒ 1
-          (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2)))
-              ⇒ (1 2 3)
-          (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2)))
-              ⇒ (2)
-
- -- Function: -max (list)
-     Return the largest value from LIST of numbers or markers.
-
-          (-max '(0))
-              ⇒ 0
-          (-max '(3 2 1))
-              ⇒ 3
-          (-max '(1 2 3))
-              ⇒ 3
-
- -- Function: -max-by (comparator list)
-     Take a comparison function COMPARATOR and a LIST and return the
-     greatest element of the list by the comparison function.
-
-     See also combinator ‘-on’ (*note -on::) which can transform the
-     values before comparing them.
-
-          (-max-by '> '(4 3 6 1))
-              ⇒ 6
-          (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2)))
-              ⇒ (3 2)
-          (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2)))
-              ⇒ (1 2 3)
-
- -- Function: -frequencies (list)
-     Count the occurrences of each distinct element of LIST.
-
-     Return an alist of (ELEMENT .  N), where each ELEMENT occurs N
-     times in LIST.
-
-     The test for equality is done with ‘equal’, or with ‘-compare-fn’
-     if that is non-‘nil’.
-
-     See also ‘-count’ (*note -count::) and ‘-group-by’ (*note
-     -group-by::).
-
-          (-frequencies ())
-              ⇒ ()
-          (-frequencies '(1 2 3 1 2 1))
-              ⇒ ((1 . 3) (2 . 2) (3 . 1))
-          (let ((-compare-fn #'string=)) (-frequencies '(a "a")))
-              ⇒ ((a . 2))
-
-\1f
-File: dash.info,  Node: Unfolding,  Next: Predicates,  Prev: Reductions,  Up: Functions
-
-2.5 Unfolding
-=============
-
-Operations dual to reductions, building lists from a seed value rather
-than consuming a list to produce a single value.
-
- -- Function: -iterate (fun init n)
-     Return a list of iterated applications of FUN to INIT.
-
-     This means a list of the form:
-
-     (INIT (FUN INIT) (FUN (FUN INIT)) ...)
-
-     N is the length of the returned list.
-
-          (-iterate #'1+ 1 10)
-              ⇒ (1 2 3 4 5 6 7 8 9 10)
-          (-iterate (lambda (x) (+ x x)) 2 5)
-              ⇒ (2 4 8 16 32)
-          (--iterate (* it it) 2 5)
-              ⇒ (2 4 16 256 65536)
-
- -- Function: -unfold (fun seed)
-     Build a list from SEED using FUN.
-
-     This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while
-     -reduce-r consumes a list to produce a single value, ‘-unfold’
-     (*note -unfold::) takes a seed value and builds a (potentially
-     infinite!)  list.
-
-     FUN should return ‘nil’ to stop the generating process, or a cons
-     (A .  B), where A will be prepended to the result and B is the new
-     seed.
-
-          (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10)
-              ⇒ (10 9 8 7 6 5 4 3 2 1)
-          (--unfold (when it (cons it (cdr it))) '(1 2 3 4))
-              ⇒ ((1 2 3 4) (2 3 4) (3 4) (4))
-          (--unfold (when it (cons it (butlast it))) '(1 2 3 4))
-              ⇒ ((1 2 3 4) (1 2 3) (1 2) (1))
-
- -- Function: -repeat (n x)
-     Return a new list of length N with each element being X.  Return
-     ‘nil’ if N is less than 1.
-
-          (-repeat 3 :a)
-              ⇒ (:a :a :a)
-          (-repeat 1 :a)
-              ⇒ (:a)
-          (-repeat 0 :a)
-              ⇒ ()
-
- -- Function: -cycle (list)
-     Return an infinite circular copy of LIST.  The returned list cycles
-     through the elements of LIST and repeats from the beginning.
-
-          (-take 5 (-cycle '(1 2 3)))
-              ⇒ (1 2 3 1 2)
-          (-take 7 (-cycle '(1 "and" 3)))
-              ⇒ (1 "and" 3 1 "and" 3 1)
-          (-zip-lists (-cycle '(3)) '(1 2))
-              ⇒ ((3 1) (3 2))
-
-\1f
-File: dash.info,  Node: Predicates,  Next: Partitioning,  Prev: Unfolding,  Up: Functions
-
-2.6 Predicates
-==============
-
-Reductions of one or more lists to a boolean value.
-
- -- Function: -some (pred list)
-     Return (PRED x) for the first LIST item where (PRED x) is
-     non-‘nil’, else ‘nil’.
-
-     Alias: ‘-any’.
-
-     This function’s anaphoric counterpart is ‘--some’.
-
-          (-some #'stringp '(1 "2" 3))
-              ⇒ t
-          (--some (string-match-p "x" it) '("foo" "axe" "xor"))
-              ⇒ 1
-          (--some (= it-index 3) '(0 1 2))
-              ⇒ nil
-
- -- Function: -every (pred list)
-     Return non-‘nil’ if PRED returns non-‘nil’ for all items in LIST.
-     If so, return the last such result of PRED.  Otherwise, once an
-     item is reached for which PRED returns ‘nil’, return ‘nil’ without
-     calling PRED on any further LIST elements.
-
-     This function is like ‘-every-p’, but on success returns the last
-     non-‘nil’ result of PRED instead of just ‘t’.
-
-     This function’s anaphoric counterpart is ‘--every’.
-
-          (-every #'numberp '(1 2 3))
-              ⇒ t
-          (--every (string-match-p "x" it) '("axe" "xor"))
-              ⇒ 0
-          (--every (= it it-index) '(0 1 3))
-              ⇒ nil
-
- -- Function: -any? (pred list)
-     Return ‘t’ if (PRED X) is non-‘nil’ for any X in LIST, else ‘nil’.
-
-     Alias: ‘-any-p’, ‘-some?’, ‘-some-p’
-
-          (-any? #'numberp '(nil 0 t))
-              ⇒ t
-          (-any? #'numberp '(nil t t))
-              ⇒ nil
-          (-any? #'null '(1 3 5))
-              ⇒ nil
-
- -- Function: -all? (pred list)
-     Return ‘t’ if (PRED X) is non-‘nil’ for all X in LIST, else ‘nil’.
-     In the latter case, stop after the first X for which (PRED X) is
-     ‘nil’, without calling PRED on any subsequent elements of LIST.
-
-     The similar function ‘-every’ (*note -every::) is more widely
-     useful, since it returns the last non-‘nil’ result of PRED instead
-     of just ‘t’ on success.
-
-     Alias: ‘-all-p’, ‘-every-p’, ‘-every?’.
-
-     This function’s anaphoric counterpart is ‘--all?’.
-
-          (-all? #'numberp '(1 2 3))
-              ⇒ t
-          (-all? #'numberp '(2 t 6))
-              ⇒ nil
-          (--all? (= 0 (% it 2)) '(2 4 6))
-              ⇒ t
-
- -- Function: -none? (pred list)
-     Return ‘t’ if (PRED X) is ‘nil’ for all X in LIST, else ‘nil’.
-
-     Alias: ‘-none-p’
-
-          (-none? 'even? '(1 2 3))
-              ⇒ nil
-          (-none? 'even? '(1 3 5))
-              ⇒ t
-          (--none? (= 0 (% it 2)) '(1 2 3))
-              ⇒ nil
-
- -- Function: -only-some? (pred list)
-     Return ‘t’ if different LIST items both satisfy and do not satisfy
-     PRED.  That is, if PRED returns both ‘nil’ for at least one item,
-     and non-‘nil’ for at least one other item in LIST.  Return ‘nil’ if
-     all items satisfy the predicate or none of them do.
-
-     Alias: ‘-only-some-p’
-
-          (-only-some? 'even? '(1 2 3))
-              ⇒ t
-          (-only-some? 'even? '(1 3 5))
-              ⇒ nil
-          (-only-some? 'even? '(2 4 6))
-              ⇒ nil
-
- -- Function: -contains? (list element)
-     Return non-‘nil’ if LIST contains ELEMENT.
-
-     The test for equality is done with ‘equal’, or with ‘-compare-fn’
-     if that is non-‘nil’.  As with ‘member’, the return value is
-     actually the tail of LIST whose car is ELEMENT.
-
-     Alias: ‘-contains-p’.
-
-          (-contains? '(1 2 3) 1)
-              ⇒ (1 2 3)
-          (-contains? '(1 2 3) 2)
-              ⇒ (2 3)
-          (-contains? '(1 2 3) 4)
-              ⇒ ()
-
- -- Function: -is-prefix? (prefix list)
-     Return non-‘nil’ if PREFIX is a prefix of LIST.
-
-     Alias: ‘-is-prefix-p’.
-
-          (-is-prefix? '(1 2 3) '(1 2 3 4 5))
-              ⇒ t
-          (-is-prefix? '(1 2 3 4 5) '(1 2 3))
-              ⇒ nil
-          (-is-prefix? '(1 3) '(1 2 3 4 5))
-              ⇒ nil
-
- -- Function: -is-suffix? (suffix list)
-     Return non-‘nil’ if SUFFIX is a suffix of LIST.
-
-     Alias: ‘-is-suffix-p’.
-
-          (-is-suffix? '(3 4 5) '(1 2 3 4 5))
-              ⇒ t
-          (-is-suffix? '(1 2 3 4 5) '(3 4 5))
-              ⇒ nil
-          (-is-suffix? '(3 5) '(1 2 3 4 5))
-              ⇒ nil
-
- -- Function: -is-infix? (infix list)
-     Return non-‘nil’ if INFIX is infix of LIST.
-
-     This operation runs in O(n^2) time
-
-     Alias: ‘-is-infix-p’
-
-          (-is-infix? '(1 2 3) '(1 2 3 4 5))
-              ⇒ t
-          (-is-infix? '(2 3 4) '(1 2 3 4 5))
-              ⇒ t
-          (-is-infix? '(3 4 5) '(1 2 3 4 5))
-              ⇒ t
-
- -- Function: -cons-pair? (obj)
-     Return non-‘nil’ if OBJ is a true cons pair.  That is, a cons (A .
-     B) where B is not a list.
-
-     Alias: ‘-cons-pair-p’.
-
-          (-cons-pair? '(1 . 2))
-              ⇒ t
-          (-cons-pair? '(1 2))
-              ⇒ nil
-          (-cons-pair? '(1))
-              ⇒ nil
-
-\1f
-File: dash.info,  Node: Partitioning,  Next: Indexing,  Prev: Predicates,  Up: Functions
-
-2.7 Partitioning
-================
-
-Functions partitioning the input list into a list of lists.
-
- -- Function: -split-at (n list)
-     Split LIST into two sublists after the Nth element.  The result is
-     a list of two elements (TAKE DROP) where TAKE is a new list of the
-     first N elements of LIST, and DROP is the remaining elements of
-     LIST (not a copy).  TAKE and DROP are like the results of ‘-take’
-     (*note -take::) and ‘-drop’ (*note -drop::), respectively, but the
-     split is done in a single list traversal.
-
-          (-split-at 3 '(1 2 3 4 5))
-              ⇒ ((1 2 3) (4 5))
-          (-split-at 17 '(1 2 3 4 5))
-              ⇒ ((1 2 3 4 5) nil)
-          (-split-at 0 '(1 2 3 4 5))
-              ⇒ (nil (1 2 3 4 5))
-
- -- Function: -split-with (pred list)
-     Split LIST into a prefix satisfying PRED, and the rest.  The first
-     sublist is the prefix of LIST with successive elements satisfying
-     PRED, and the second sublist is the remaining elements that do not.
-     The result is like performing
-
-     ((-take-while PRED LIST) (-drop-while PRED LIST))
-
-     but in no more than a single pass through LIST.
-
-          (-split-with 'even? '(1 2 3 4))
-              ⇒ (nil (1 2 3 4))
-          (-split-with 'even? '(2 4 5 6))
-              ⇒ ((2 4) (5 6))
-          (--split-with (< it 4) '(1 2 3 4 3 2 1))
-              ⇒ ((1 2 3) (4 3 2 1))
-
- -- Macro: -split-on (item list)
-     Split the LIST each time ITEM is found.
-
-     Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is
-     discarded from the results.  Empty lists are also removed from the
-     result.
-
-     Comparison is done by ‘equal’.
-
-     See also ‘-split-when’ (*note -split-when::)
-
-          (-split-on '| '(Nil | Leaf a | Node [Tree a]))
-              ⇒ ((Nil) (Leaf a) (Node [Tree a]))
-          (-split-on :endgroup '("a" "b" :endgroup "c" :endgroup "d" "e"))
-              ⇒ (("a" "b") ("c") ("d" "e"))
-          (-split-on :endgroup '("a" "b" :endgroup :endgroup "d" "e"))
-              ⇒ (("a" "b") ("d" "e"))
-
- -- Function: -split-when (fn list)
-     Split the LIST on each element where FN returns non-‘nil’.
-
-     Unlike ‘-partition-by’ (*note -partition-by::), the "matched"
-     element is discarded from the results.  Empty lists are also
-     removed from the result.
-
-     This function can be thought of as a generalization of
-     ‘split-string’.
-
-          (-split-when 'even? '(1 2 3 4 5 6))
-              ⇒ ((1) (3) (5))
-          (-split-when 'even? '(1 2 3 4 6 8 9))
-              ⇒ ((1) (3) (9))
-          (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args))
-              ⇒ ((a b) (c d) (args))
-
- -- Function: -separate (pred list)
-     Split LIST into two sublists based on whether items satisfy PRED.
-     The result is like performing
-
-     ((-filter PRED LIST) (-remove PRED LIST))
-
-     but in a single pass through LIST.
-
-          (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7))
-              ⇒ ((2 4 6) (1 3 5 7))
-          (--separate (< it 5) '(3 7 5 9 3 2 1 4 6))
-              ⇒ ((3 3 2 1 4) (7 5 9 6))
-          (-separate 'cdr '((1 2) (1) (1 2 3) (4)))
-              ⇒ (((1 2) (1 2 3)) ((1) (4)))
-
- -- Function: -partition (n list)
-     Return a new list with the items in LIST grouped into N-sized
-     sublists.  If there are not enough items to make the last group
-     N-sized, those items are discarded.
-
-          (-partition 2 '(1 2 3 4 5 6))
-              ⇒ ((1 2) (3 4) (5 6))
-          (-partition 2 '(1 2 3 4 5 6 7))
-              ⇒ ((1 2) (3 4) (5 6))
-          (-partition 3 '(1 2 3 4 5 6 7))
-              ⇒ ((1 2 3) (4 5 6))
-
- -- Function: -partition-all (n list)
-     Return a new list with the items in LIST grouped into N-sized
-     sublists.  The last group may contain less than N items.
-
-          (-partition-all 2 '(1 2 3 4 5 6))
-              ⇒ ((1 2) (3 4) (5 6))
-          (-partition-all 2 '(1 2 3 4 5 6 7))
-              ⇒ ((1 2) (3 4) (5 6) (7))
-          (-partition-all 3 '(1 2 3 4 5 6 7))
-              ⇒ ((1 2 3) (4 5 6) (7))
-
- -- Function: -partition-in-steps (n step list)
-     Partition LIST into sublists of length N that are STEP items apart.
-     Like ‘-partition-all-in-steps’ (*note -partition-all-in-steps::),
-     but if there are not enough items to make the last group N-sized,
-     those items are discarded.
-
-          (-partition-in-steps 2 1 '(1 2 3 4))
-              ⇒ ((1 2) (2 3) (3 4))
-          (-partition-in-steps 3 2 '(1 2 3 4))
-              ⇒ ((1 2 3))
-          (-partition-in-steps 3 2 '(1 2 3 4 5))
-              ⇒ ((1 2 3) (3 4 5))
-
- -- Function: -partition-all-in-steps (n step list)
-     Partition LIST into sublists of length N that are STEP items apart.
-     Adjacent groups may overlap if N exceeds the STEP stride.  Trailing
-     groups may contain less than N items.
-
-          (-partition-all-in-steps 2 1 '(1 2 3 4))
-              ⇒ ((1 2) (2 3) (3 4) (4))
-          (-partition-all-in-steps 3 2 '(1 2 3 4))
-              ⇒ ((1 2 3) (3 4))
-          (-partition-all-in-steps 3 2 '(1 2 3 4 5))
-              ⇒ ((1 2 3) (3 4 5) (5))
-
- -- Function: -partition-by (fn list)
-     Apply FN to each item in LIST, splitting it each time FN returns a
-     new value.
-
-          (-partition-by 'even? ())
-              ⇒ ()
-          (-partition-by 'even? '(1 1 2 2 2 3 4 6 8))
-              ⇒ ((1 1) (2 2 2) (3) (4 6 8))
-          (--partition-by (< it 3) '(1 2 3 4 3 2 1))
-              ⇒ ((1 2) (3 4 3) (2 1))
-
- -- Function: -partition-by-header (fn list)
-     Apply FN to the first item in LIST.  That is the header value.
-     Apply FN to each item in LIST, splitting it each time FN returns
-     the header value, but only after seeing at least one other value
-     (the body).
-
-          (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4))
-              ⇒ ((1 2 3) (1 2) (1 2 3 4))
-          (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0))
-              ⇒ ((1 2 0) (1 0) (1 2 3 0))
-          (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1))
-              ⇒ ((2 1 1 1) (4 1 3 5) (6 6 1))
-
- -- Function: -partition-after-pred (pred list)
-     Partition LIST after each element for which PRED returns non-‘nil’.
-
-     This function’s anaphoric counterpart is ‘--partition-after-pred’.
-
-          (-partition-after-pred #'booleanp ())
-              ⇒ ()
-          (-partition-after-pred #'booleanp '(t t))
-              ⇒ ((t) (t))
-          (-partition-after-pred #'booleanp '(0 0 t t 0 t))
-              ⇒ ((0 0 t) (t) (0 t))
-
- -- Function: -partition-before-pred (pred list)
-     Partition directly before each time PRED is true on an element of
-     LIST.
-
-          (-partition-before-pred #'booleanp ())
-              ⇒ ()
-          (-partition-before-pred #'booleanp '(0 t))
-              ⇒ ((0) (t))
-          (-partition-before-pred #'booleanp '(0 0 t 0 t t))
-              ⇒ ((0 0) (t 0) (t) (t))
-
- -- Function: -partition-before-item (item list)
-     Partition directly before each time ITEM appears in LIST.
-
-          (-partition-before-item 3 ())
-              ⇒ ()
-          (-partition-before-item 3 '(1))
-              ⇒ ((1))
-          (-partition-before-item 3 '(3))
-              ⇒ ((3))
-
- -- Function: -partition-after-item (item list)
-     Partition directly after each time ITEM appears in LIST.
-
-          (-partition-after-item 3 ())
-              ⇒ ()
-          (-partition-after-item 3 '(1))
-              ⇒ ((1))
-          (-partition-after-item 3 '(3))
-              ⇒ ((3))
-
- -- Function: -group-by (fn list)
-     Separate LIST into an alist whose keys are FN applied to the
-     elements of LIST.  Keys are compared by ‘equal’.
-
-          (-group-by 'even? ())
-              ⇒ ()
-          (-group-by 'even? '(1 1 2 2 2 3 4 6 8))
-              ⇒ ((nil 1 1 3) (t 2 2 2 4 6 8))
-          (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e"))
-              ⇒ (("a" "a/b" "a/e") ("c" "c/d"))
-
-\1f
-File: dash.info,  Node: Indexing,  Next: Set operations,  Prev: Partitioning,  Up: Functions
-
-2.8 Indexing
-============
-
-Functions retrieving or sorting based on list indices and related
-predicates.
-
- -- Function: -elem-index (elem list)
-     Return the first index of ELEM in LIST.  That is, the index within
-     LIST of the first element that is ‘equal’ to ELEM.  Return ‘nil’ if
-     there is no such element.
-
-     See also: ‘-find-index’ (*note -find-index::).
-
-          (-elem-index 2 '(6 7 8 3 4))
-              ⇒ nil
-          (-elem-index "bar" '("foo" "bar" "baz"))
-              ⇒ 1
-          (-elem-index '(1 2) '((3) (5 6) (1 2) nil))
-              ⇒ 2
-
- -- Function: -elem-indices (elem list)
-     Return the list of indices at which ELEM appears in LIST.  That is,
-     the indices of all elements of LIST ‘equal’ to ELEM, in the same
-     ascending order as they appear in LIST.
-
-          (-elem-indices 2 '(6 7 8 3 4 1))
-              ⇒ ()
-          (-elem-indices "bar" '("foo" "bar" "baz"))
-              ⇒ (1)
-          (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil))
-              ⇒ (1 3)
-
- -- Function: -find-index (pred list)
-     Return the index of the first item satisfying PRED in LIST.  Return
-     ‘nil’ if no such item is found.
-
-     PRED is called with one argument, the current list element, until
-     it returns non-‘nil’, at which point the search terminates.
-
-     This function’s anaphoric counterpart is ‘--find-index’.
-
-     See also: ‘-first’ (*note -first::), ‘-find-last-index’ (*note
-     -find-last-index::).
-
-          (-find-index #'numberp '(a b c))
-              ⇒ nil
-          (-find-index #'natnump '(1 0 -1))
-              ⇒ 0
-          (--find-index (> it 5) '(2 4 1 6 3 3 5 8))
-              ⇒ 3
-
- -- Function: -find-last-index (pred list)
-     Return the index of the last item satisfying PRED in LIST.  Return
-     ‘nil’ if no such item is found.
-
-     Predicate PRED is called with one argument each time, namely the
-     current list element.
-
-     This function’s anaphoric counterpart is ‘--find-last-index’.
-
-     See also: ‘-last’ (*note -last::), ‘-find-index’ (*note
-     -find-index::).
-
-          (-find-last-index #'numberp '(a b c))
-              ⇒ nil
-          (--find-last-index (> it 5) '(2 7 1 6 3 8 5 2))
-              ⇒ 5
-          (-find-last-index (-partial #'string< 'a) '(c b a))
-              ⇒ 1
-
- -- Function: -find-indices (pred list)
-     Return the list of indices in LIST satisfying PRED.
-
-     Each element of LIST in turn is passed to PRED.  If the result is
-     non-‘nil’, the index of that element in LIST is included in the
-     result.  The returned indices are in ascending order, i.e., in the
-     same order as they appear in LIST.
-
-     This function’s anaphoric counterpart is ‘--find-indices’.
-
-     See also: ‘-find-index’ (*note -find-index::), ‘-elem-indices’
-     (*note -elem-indices::).
-
-          (-find-indices #'numberp '(a b c))
-              ⇒ ()
-          (-find-indices #'numberp '(8 1 d 2 b c a 3))
-              ⇒ (0 1 3 7)
-          (--find-indices (> it 5) '(2 4 1 6 3 3 5 8))
-              ⇒ (3 7)
-
- -- Function: -grade-up (comparator list)
-     Grade elements of LIST using COMPARATOR relation.  This yields a
-     permutation vector such that applying this permutation to LIST
-     sorts it in ascending order.
-
-          (-grade-up #'< '(3 1 4 2 1 3 3))
-              ⇒ (1 4 3 0 5 6 2)
-          (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up #'< l) l))
-              ⇒ (1 1 2 3 3 3 4)
-
- -- Function: -grade-down (comparator list)
-     Grade elements of LIST using COMPARATOR relation.  This yields a
-     permutation vector such that applying this permutation to LIST
-     sorts it in descending order.
-
-          (-grade-down #'< '(3 1 4 2 1 3 3))
-              ⇒ (2 0 5 6 3 1 4)
-          (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down #'< l) l))
-              ⇒ (4 3 3 3 2 1 1)
-
-\1f
-File: dash.info,  Node: Set operations,  Next: Other list operations,  Prev: Indexing,  Up: Functions
-
-2.9 Set operations
-==================
-
-Operations pretending lists are sets.
-
- -- Function: -union (list1 list2)
-     Return a new list of distinct elements appearing in either LIST1 or
-     LIST2.
-
-     The test for equality is done with ‘equal’, or with ‘-compare-fn’
-     if that is non-‘nil’.
-
-          (-union '(1 2 3) '(3 4 5))
-              ⇒ (1 2 3 4 5)
-          (-union '(1 2 2 4) ())
-              ⇒ (1 2 4)
-          (-union '(1 1 2 2) '(4 4 3 2 1))
-              ⇒ (1 2 4 3)
-
- -- Function: -difference (list1 list2)
-     Return a new list with the distinct members of LIST1 that are not
-     in LIST2.
-
-     The test for equality is done with ‘equal’, or with ‘-compare-fn’
-     if that is non-‘nil’.
-
-          (-difference () ())
-              ⇒ ()
-          (-difference '(1 2 3) '(4 5 6))
-              ⇒ (1 2 3)
-          (-difference '(1 2 3 4) '(3 4 5 6))
-              ⇒ (1 2)
-
- -- Function: -intersection (list1 list2)
-     Return a new list of distinct elements appearing in both LIST1 and
-     LIST2.
-
-     The test for equality is done with ‘equal’, or with ‘-compare-fn’
-     if that is non-‘nil’.
-
-          (-intersection () ())
-              ⇒ ()
-          (-intersection '(1 2 3) '(4 5 6))
-              ⇒ ()
-          (-intersection '(1 2 2 3) '(4 3 3 2))
-              ⇒ (2 3)
-
- -- Function: -powerset (list)
-     Return the power set of LIST.
-
-          (-powerset ())
-              ⇒ (nil)
-          (-powerset '(x y))
-              ⇒ ((x y) (x) (y) nil)
-          (-powerset '(x y z))
-              ⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil)
-
- -- Function: -permutations (list)
-     Return the distinct permutations of LIST.
-
-     Duplicate elements of LIST are determined by ‘equal’, or by
-     ‘-compare-fn’ if that is non-‘nil’.
-
-          (-permutations ())
-              ⇒ (nil)
-          (-permutations '(a a b))
-              ⇒ ((a a b) (a b a) (b a a))
-          (-permutations '(a b c))
-              ⇒ ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))
-
- -- Function: -distinct (list)
-     Return a copy of LIST with all duplicate elements removed.
-
-     The test for equality is done with ‘equal’, or with ‘-compare-fn’
-     if that is non-‘nil’.
-
-     Alias: ‘-uniq’.
-
-          (-distinct ())
-              ⇒ ()
-          (-distinct '(1 1 2 3 3))
-              ⇒ (1 2 3)
-          (-distinct '(t t t))
-              ⇒ (t)
-
- -- Function: -same-items? (list1 list2)
-     Return non-‘nil’ if LIST1 and LIST2 have the same distinct
-     elements.
-
-     The order of the elements in the lists does not matter.  The lists
-     may be of different lengths, i.e., contain duplicate elements.  The
-     test for equality is done with ‘equal’, or with ‘-compare-fn’ if
-     that is non-‘nil’.
-
-     Alias: ‘-same-items-p’.
-
-          (-same-items? '(1 2 3) '(1 2 3))
-              ⇒ t
-          (-same-items? '(1 1 2 3) '(3 3 2 1))
-              ⇒ t
-          (-same-items? '(1 2 3) '(1 2 3 4))
-              ⇒ nil
-
-\1f
-File: dash.info,  Node: Other list operations,  Next: Tree operations,  Prev: Set operations,  Up: Functions
-
-2.10 Other list operations
-==========================
-
-Other list functions not fit to be classified elsewhere.
-
- -- Function: -rotate (n list)
-     Rotate LIST N places to the right (left if N is negative).  The
-     time complexity is O(n).
-
-          (-rotate 3 '(1 2 3 4 5 6 7))
-              ⇒ (5 6 7 1 2 3 4)
-          (-rotate -3 '(1 2 3 4 5 6 7))
-              ⇒ (4 5 6 7 1 2 3)
-          (-rotate 16 '(1 2 3 4 5 6 7))
-              ⇒ (6 7 1 2 3 4 5)
-
- -- Function: -cons* (&rest args)
-     Make a new list from the elements of ARGS.  The last 2 elements of
-     ARGS are used as the final cons of the result, so if the final
-     element of ARGS is not a list, the result is a dotted list.  With
-     no ARGS, return ‘nil’.
-
-          (-cons* 1 2)
-              ⇒ (1 . 2)
-          (-cons* 1 2 3)
-              ⇒ (1 2 . 3)
-          (-cons* 1)
-              ⇒ 1
-
- -- Function: -snoc (list elem &rest elements)
-     Append ELEM to the end of the list.
-
-     This is like ‘cons’, but operates on the end of list.
-
-     If any ELEMENTS are given, append them to the list as well.
-
-          (-snoc '(1 2 3) 4)
-              ⇒ (1 2 3 4)
-          (-snoc '(1 2 3) 4 5 6)
-              ⇒ (1 2 3 4 5 6)
-          (-snoc '(1 2 3) '(4 5 6))
-              ⇒ (1 2 3 (4 5 6))
-
- -- Function: -interpose (sep list)
-     Return a new list of all elements in LIST separated by SEP.
-
-          (-interpose "-" ())
-              ⇒ ()
-          (-interpose "-" '("a"))
-              ⇒ ("a")
-          (-interpose "-" '("a" "b" "c"))
-              ⇒ ("a" "-" "b" "-" "c")
-
- -- Function: -interleave (&rest lists)
-     Return a new list of the first item in each list, then the second
-     etc.
-
-          (-interleave '(1 2) '("a" "b"))
-              ⇒ (1 "a" 2 "b")
-          (-interleave '(1 2) '("a" "b") '("A" "B"))
-              ⇒ (1 "a" "A" 2 "b" "B")
-          (-interleave '(1 2 3) '("a" "b"))
-              ⇒ (1 "a" 2 "b")
-
- -- Function: -iota (count &optional start step)
-     Return a list containing COUNT numbers.  Starts from START and adds
-     STEP each time.  The default START is zero, the default STEP is 1.
-     This function takes its name from the corresponding primitive in
-     the APL language.
-
-          (-iota 6)
-              ⇒ (0 1 2 3 4 5)
-          (-iota 4 2.5 -2)
-              ⇒ (2.5 0.5 -1.5 -3.5)
-          (-iota -1)
-              error→ Wrong type argument: natnump, -1
-
- -- Function: -zip-with (fn list1 list2)
-     Zip LIST1 and LIST2 into a new list using the function FN.  That
-     is, apply FN pairwise taking as first argument the next element of
-     LIST1 and as second argument the next element of LIST2 at the
-     corresponding position.  The result is as long as the shorter list.
-
-     This function’s anaphoric counterpart is ‘--zip-with’.
-
-     For other zips, see also ‘-zip-lists’ (*note -zip-lists::) and
-     ‘-zip-fill’ (*note -zip-fill::).
-
-          (-zip-with #'+ '(1 2 3 4) '(5 6 7))
-              ⇒ (6 8 10)
-          (-zip-with #'cons '(1 2 3) '(4 5 6 7))
-              ⇒ ((1 . 4) (2 . 5) (3 . 6))
-          (--zip-with (format "%s & %s" it other) '(Batman Jekyll) '(Robin Hyde))
-              ⇒ ("Batman & Robin" "Jekyll & Hyde")
-
- -- Function: -zip-pair (list1 list2)
-     Zip LIST1 and LIST2 together.
-
-     Make a pair with the head of each list, followed by a pair with the
-     second element of each list, and so on.  The number of pairs
-     returned is equal to the length of the shorter input list.
-
-     See also: ‘-zip-lists’ (*note -zip-lists::).
-
-          (-zip-pair '(1 2 3 4) '(5 6 7))
-              ⇒ ((1 . 5) (2 . 6) (3 . 7))
-          (-zip-pair '(1 2 3) '(4 5 6))
-              ⇒ ((1 . 4) (2 . 5) (3 . 6))
-          (-zip-pair '(1 2) '(3))
-              ⇒ ((1 . 3))
-
- -- Function: -zip-lists (&rest lists)
-     Zip LISTS together.
-
-     Group the head of each list, followed by the second element of each
-     list, and so on.  The number of returned groupings is equal to the
-     length of the shortest input list, and the length of each grouping
-     is equal to the number of input LISTS.
-
-     The return value is always a list of proper lists, in contrast to
-     ‘-zip’ (*note -zip::) which returns a list of dotted pairs when
-     only two input LISTS are provided.
-
-     See also: ‘-zip-pair’ (*note -zip-pair::).
-
-          (-zip-lists '(1 2 3) '(4 5 6))
-              ⇒ ((1 4) (2 5) (3 6))
-          (-zip-lists '(1 2 3) '(4 5 6 7))
-              ⇒ ((1 4) (2 5) (3 6))
-          (-zip-lists '(1 2) '(3 4 5) '(6))
-              ⇒ ((1 3 6))
-
- -- Function: -zip-lists-fill (fill-value &rest lists)
-     Zip LISTS together, padding shorter lists with FILL-VALUE.  This is
-     like ‘-zip-lists’ (*note -zip-lists::) (which see), except it
-     retains all elements at positions beyond the end of the shortest
-     list.  The number of returned groupings is equal to the length of
-     the longest input list, and the length of each grouping is equal to
-     the number of input LISTS.
-
-          (-zip-lists-fill 0 '(1 2) '(3 4 5) '(6))
-              ⇒ ((1 3 6) (2 4 0) (0 5 0))
-          (-zip-lists-fill 0 '(1 2) '(3 4) '(5 6))
-              ⇒ ((1 3 5) (2 4 6))
-          (-zip-lists-fill 0 '(1 2 3) nil)
-              ⇒ ((1 0) (2 0) (3 0))
-
- -- Function: -zip (&rest lists)
-     Zip LISTS together.
-
-     Group the head of each list, followed by the second element of each
-     list, and so on.  The number of returned groupings is equal to the
-     length of the shortest input list, and the number of items in each
-     grouping is equal to the number of input LISTS.
-
-     If only two LISTS are provided as arguments, return the groupings
-     as a list of dotted pairs.  Otherwise, return the groupings as a
-     list of proper lists.
-
-     Since the return value changes form depending on the number of
-     arguments, it is generally recommended to use ‘-zip-lists’ (*note
-     -zip-lists::) instead, or ‘-zip-pair’ (*note -zip-pair::) if a list
-     of dotted pairs is desired.
-
-     See also: ‘-unzip’ (*note -unzip::).
-
-          (-zip '(1 2 3 4) '(5 6 7) '(8 9))
-              ⇒ ((1 5 8) (2 6 9))
-          (-zip '(1 2 3) '(4 5 6) '(7 8 9))
-              ⇒ ((1 4 7) (2 5 8) (3 6 9))
-          (-zip '(1 2 3))
-              ⇒ ((1) (2) (3))
-
- -- Function: -zip-fill (fill-value &rest lists)
-     Zip LISTS together, padding shorter lists with FILL-VALUE.  This is
-     like ‘-zip’ (*note -zip::) (which see), except it retains all
-     elements at positions beyond the end of the shortest list.  The
-     number of returned groupings is equal to the length of the longest
-     input list, and the length of each grouping is equal to the number
-     of input LISTS.
-
-     Since the return value changes form depending on the number of
-     arguments, it is generally recommended to use ‘-zip-lists-fill’
-     (*note -zip-lists-fill::) instead, unless a list of dotted pairs is
-     explicitly desired.
-
-          (-zip-fill 0 '(1 2 3) '(4 5))
-              ⇒ ((1 . 4) (2 . 5) (3 . 0))
-          (-zip-fill 0 () '(1 2 3))
-              ⇒ ((0 . 1) (0 . 2) (0 . 3))
-          (-zip-fill 0 '(1 2) '(3 4) '(5 6))
-              ⇒ ((1 3 5) (2 4 6))
-
- -- Function: -unzip-lists (lists)
-     Unzip LISTS.
-
-     This works just like ‘-zip-lists’ (*note -zip-lists::) (which see),
-     but takes a list of lists instead of a variable number of
-     arguments, such that
-
-     (-unzip-lists (-zip-lists ARGS...))
-
-     is identity (given that the lists comprising ARGS are of the same
-     length).
-
-          (-unzip-lists (-zip-lists '(1 2) '(3 4) '(5 6)))
-              ⇒ ((1 2) (3 4) (5 6))
-          (-unzip-lists '((1 2 3) (4 5) (6 7) (8 9)))
-              ⇒ ((1 4 6 8) (2 5 7 9))
-          (-unzip-lists '((1 2 3) (4 5 6)))
-              ⇒ ((1 4) (2 5) (3 6))
-
- -- Function: -unzip (lists)
-     Unzip LISTS.
-
-     This works just like ‘-zip’ (*note -zip::) (which see), but takes a
-     list of lists instead of a variable number of arguments, such that
-
-     (-unzip (-zip L1 L2 L3 ...))
-
-     is identity (given that the lists are of the same length, and that
-     ‘-zip’ (*note -zip::) is not called with two arguments, because of
-     the caveat described in its docstring).
-
-     Note in particular that calling ‘-unzip’ (*note -unzip::) on a list
-     of two lists will return a list of dotted pairs.
-
-     Since the return value changes form depending on the number of
-     LISTS, it is generally recommended to use ‘-unzip-lists’ (*note
-     -unzip-lists::) instead.
-
-          (-unzip (-zip '(1 2) '(3 4) '(5 6)))
-              ⇒ ((1 . 2) (3 . 4) (5 . 6))
-          (-unzip '((1 2 3) (4 5 6)))
-              ⇒ ((1 . 4) (2 . 5) (3 . 6))
-          (-unzip '((1 2 3) (4 5) (6 7) (8 9)))
-              ⇒ ((1 4 6 8) (2 5 7 9))
-
- -- Function: -pad (fill-value &rest lists)
-     Pad each of LISTS with FILL-VALUE until they all have equal
-     lengths.
-
-     Ensure all LISTS are as long as the longest one by repeatedly
-     appending FILL-VALUE to the shorter lists, and return the resulting
-     LISTS.
-
-          (-pad 0 ())
-              ⇒ (nil)
-          (-pad 0 '(1 2) '(3 4))
-              ⇒ ((1 2) (3 4))
-          (-pad 0 '(1 2) '(3 4 5 6) '(7 8 9))
-              ⇒ ((1 2 0 0) (3 4 5 6) (7 8 9 0))
-
- -- Function: -table (fn &rest lists)
-     Compute outer product of LISTS using function FN.
-
-     The function FN should have the same arity as the number of
-     supplied lists.
-
-     The outer product is computed by applying fn to all possible
-     combinations created by taking one element from each list in order.
-     The dimension of the result is (length lists).
-
-     See also: ‘-table-flat’ (*note -table-flat::)
-
-          (-table '* '(1 2 3) '(1 2 3))
-              ⇒ ((1 2 3) (2 4 6) (3 6 9))
-          (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4)))
-              ⇒ ((7 15) (10 22))
-          (apply '-table 'list (-repeat 3 '(1 2)))
-              ⇒ ((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2))))
-
- -- Function: -table-flat (fn &rest lists)
-     Compute flat outer product of LISTS using function FN.
-
-     The function FN should have the same arity as the number of
-     supplied lists.
-
-     The outer product is computed by applying fn to all possible
-     combinations created by taking one element from each list in order.
-     The results are flattened, ignoring the tensor structure of the
-     result.  This is equivalent to calling:
-
-     (-flatten-n (1- (length lists)) (apply ’-table fn lists))
-
-     but the implementation here is much more efficient.
-
-     See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note
-     -table::)
-
-          (-table-flat 'list '(1 2 3) '(a b c))
-              ⇒ ((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c))
-          (-table-flat '* '(1 2 3) '(1 2 3))
-              ⇒ (1 2 3 2 4 6 3 6 9)
-          (apply '-table-flat 'list (-repeat 3 '(1 2)))
-              ⇒ ((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2))
-
- -- Function: -first (pred list)
-     Return the first item in LIST for which PRED returns non-‘nil’.
-     Return ‘nil’ if no such element is found.
-
-     To get the first item in the list no questions asked, use
-     ‘-first-item’ (*note -first-item::).
-
-     Alias: ‘-find’.
-
-     This function’s anaphoric counterpart is ‘--first’.
-
-          (-first #'natnump '(-1 0 1))
-              ⇒ 0
-          (-first #'null '(1 2 3))
-              ⇒ nil
-          (--first (> it 2) '(1 2 3))
-              ⇒ 3
-
- -- Function: -last (pred list)
-     Return the last x in LIST where (PRED x) is non-‘nil’, else ‘nil’.
-
-          (-last 'even? '(1 2 3 4 5 6 3 3 3))
-              ⇒ 6
-          (-last 'even? '(1 3 7 5 9))
-              ⇒ nil
-          (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one"))
-              ⇒ "short"
-
- -- Function: -first-item (list)
-     Return the first item of LIST, or ‘nil’ on an empty list.
-
-     See also: ‘-second-item’ (*note -second-item::), ‘-last-item’
-     (*note -last-item::), etc.
-
-          (-first-item ())
-              ⇒ ()
-          (-first-item '(1 2 3 4 5))
-              ⇒ 1
-          (let ((list (list 1 2 3))) (setf (-first-item list) 5) list)
-              ⇒ (5 2 3)
-
- -- Function: -second-item (list)
-     Return the second item of LIST, or ‘nil’ if LIST is too short.
-
-     See also: ‘-first-item’ (*note -first-item::), ‘-third-item’ (*note
-     -third-item::), etc.
-
-          (-second-item ())
-              ⇒ ()
-          (-second-item '(1 2 3 4 5))
-              ⇒ 2
-          (let ((list (list 1 2))) (setf (-second-item list) 5) list)
-              ⇒ (1 5)
-
- -- Function: -third-item (list)
-     Return the third item of LIST, or ‘nil’ if LIST is too short.
-
-     See also: ‘-second-item’ (*note -second-item::), ‘-fourth-item’
-     (*note -fourth-item::), etc.
-
-          (-third-item ())
-              ⇒ ()
-          (-third-item '(1 2))
-              ⇒ ()
-          (-third-item '(1 2 3 4 5))
-              ⇒ 3
-
- -- Function: -fourth-item (list)
-     Return the fourth item of LIST, or ‘nil’ if LIST is too short.
-
-     See also: ‘-third-item’ (*note -third-item::), ‘-fifth-item’ (*note
-     -fifth-item::), etc.
-
-          (-fourth-item ())
-              ⇒ ()
-          (-fourth-item '(1 2 3))
-              ⇒ ()
-          (-fourth-item '(1 2 3 4 5))
-              ⇒ 4
-
- -- Function: -fifth-item (list)
-     Return the fifth item of LIST, or ‘nil’ if LIST is too short.
-
-     See also: ‘-fourth-item’ (*note -fourth-item::), ‘-last-item’
-     (*note -last-item::), etc.
-
-          (-fifth-item ())
-              ⇒ ()
-          (-fifth-item '(1 2 3 4))
-              ⇒ ()
-          (-fifth-item '(1 2 3 4 5))
-              ⇒ 5
-
- -- Function: -last-item (list)
-     Return the last item of LIST, or ‘nil’ on an empty list.
-
-     See also: ‘-first-item’ (*note -first-item::), etc.
-
-          (-last-item ())
-              ⇒ ()
-          (-last-item '(1 2 3 4 5))
-              ⇒ 5
-          (let ((list (list 1 2 3))) (setf (-last-item list) 5) list)
-              ⇒ (1 2 5)
-
- -- Function: -butlast (list)
-     Return a list of all items in list except for the last.
-
-          (-butlast '(1 2 3))
-              ⇒ (1 2)
-          (-butlast '(1 2))
-              ⇒ (1)
-          (-butlast '(1))
-              ⇒ nil
-
- -- Function: -sort (comparator list)
-     Sort LIST, stably, comparing elements using COMPARATOR.  Return the
-     sorted list.  LIST is NOT modified by side effects.  COMPARATOR is
-     called with two elements of LIST, and should return non-‘nil’ if
-     the first element should sort before the second.
-
-          (-sort #'< '(3 1 2))
-              ⇒ (1 2 3)
-          (-sort #'> '(3 1 2))
-              ⇒ (3 2 1)
-          (--sort (< it other) '(3 1 2))
-              ⇒ (1 2 3)
-
- -- Function: -list (arg)
-     Ensure ARG is a list.  If ARG is already a list, return it as is
-     (not a copy).  Otherwise, return a new list with ARG as its only
-     element.
-
-     Another supported calling convention is (-list &rest ARGS).  In
-     this case, if ARG is not a list, a new list with all of ARGS as
-     elements is returned.  This use is supported for backward
-     compatibility and is otherwise deprecated.
-
-          (-list 1)
-              ⇒ (1)
-          (-list ())
-              ⇒ ()
-          (-list '(1 2 3))
-              ⇒ (1 2 3)
-
- -- Function: -fix (fn list)
-     Compute the (least) fixpoint of FN with initial input LIST.
-
-     FN is called at least once, results are compared with ‘equal’.
-
-          (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3)))
-              ⇒ ((1) (2) (3))
-          (let ((l '((starwars scifi) (jedi starwars warrior)))) (--fix (-uniq (--mapcat (cons it (cdr (assq it l))) it)) '(jedi book)))
-              ⇒ (jedi starwars warrior scifi book)
-
-\1f
-File: dash.info,  Node: Tree operations,  Next: Threading macros,  Prev: Other list operations,  Up: Functions
-
-2.11 Tree operations
-====================
-
-Functions pretending lists are trees.
-
- -- Function: -tree-seq (branch children tree)
-     Return a sequence of the nodes in TREE, in depth-first search
-     order.
-
-     BRANCH is a predicate of one argument that returns non-‘nil’ if the
-     passed argument is a branch, that is, a node that can have
-     children.
-
-     CHILDREN is a function of one argument that returns the children of
-     the passed branch node.
-
-     Non-branch nodes are simply copied.
-
-          (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7))))
-              ⇒ ((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7)
-          (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7))))
-              ⇒ ((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1)
-          (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]])
-              ⇒ ([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7)
-
- -- Function: -tree-map (fn tree)
-     Apply FN to each element of TREE while preserving the tree
-     structure.
-
-          (-tree-map '1+ '(1 (2 3) (4 (5 6) 7)))
-              ⇒ (2 (3 4) (5 (6 7) 8))
-          (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4))
-              ⇒ ((1 . 2) ((2 . 4) (3 . 8)) (4 . 16))
-          (--tree-map (length it) '("<body>" ("<p>" "text" "</p>") "</body>"))
-              ⇒ (6 (3 4 4) 7)
-
- -- Function: -tree-map-nodes (pred fun tree)
-     Call FUN on each node of TREE that satisfies PRED.
-
-     If PRED returns ‘nil’, continue descending down this node.  If PRED
-     returns non-‘nil’, apply FUN to this node and do not descend
-     further.
-
-          (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8)))
-              ⇒ (1 5 4 (5 13 8))
-          (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8)))
-              ⇒ (1 ":foo" 4 ((5 6 ":bar") ":baz" 8))
-          (--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d))))
-              ⇒ (with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode)))
-
- -- Function: -tree-reduce (fn tree)
-     Use FN to reduce elements of list TREE.  If elements of TREE are
-     lists themselves, apply the reduction recursively.
-
-     FN is first applied to first element of the list and second
-     element, then on this result and third element from the list etc.
-
-     See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of
-     zero or one element handled.
-
-          (-tree-reduce '+ '(1 (2 3) (4 5)))
-              ⇒ 15
-          (-tree-reduce 'concat '("strings" (" on" " various") ((" levels"))))
-              ⇒ "strings on various levels"
-          (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "</" sn ">")))) '(body (p "some words") (div "more" (b "bold") "words")))
-              ⇒ "<body><p>some words</p> <div>more <b>bold</b> words</div></body>"
-
- -- Function: -tree-reduce-from (fn init-value tree)
-     Use FN to reduce elements of list TREE.  If elements of TREE are
-     lists themselves, apply the reduction recursively.
-
-     FN is first applied to INIT-VALUE and first element of the list,
-     then on this result and second element from the list etc.
-
-     The initial value is ignored on cons pairs as they always contain
-     two elements.
-
-          (-tree-reduce-from '+ 1 '(1 (1 1) ((1))))
-              ⇒ 8
-          (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7)))
-              ⇒ ((7 6) ((5 4) 3 2) 1)
-
- -- Function: -tree-mapreduce (fn folder tree)
-     Apply FN to each element of TREE, and make a list of the results.
-     If elements of TREE are lists themselves, apply FN recursively to
-     elements of these nested lists.
-
-     Then reduce the resulting lists using FOLDER and initial value
-     INIT-VALUE.  See ‘-reduce-r-from’ (*note -reduce-r-from::).
-
-     This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::)
-     after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it
-     only traverse the structure once.
-
-          (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9))))
-              ⇒ (1 2 3 4 5 6 7 8 9)
-          (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3))))
-              ⇒ 9
-          (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3))))
-              ⇒ 3
-
- -- Function: -tree-mapreduce-from (fn folder init-value tree)
-     Apply FN to each element of TREE, and make a list of the results.
-     If elements of TREE are lists themselves, apply FN recursively to
-     elements of these nested lists.
-
-     Then reduce the resulting lists using FOLDER and initial value
-     INIT-VALUE.  See ‘-reduce-r-from’ (*note -reduce-r-from::).
-
-     This is the same as calling ‘-tree-reduce-from’ (*note
-     -tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is
-     twice as fast as it only traverse the structure once.
-
-          (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9))))
-              ⇒ 362880
-          (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3))))
-              ⇒ (2 (4 (8 18) (4 2)) (14 (8 6)))
-          (concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elisp-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam)))))
-              ⇒ "{elisp-mode : {foo : {bar -> booze}, baz -> qux}, c-mode : {foo -> bla, bum -> bam}}"
-
- -- Function: -clone (list)
-     Create a deep copy of LIST.  The new list has the same elements and
-     structure but all cons are replaced with new ones.  This is useful
-     when you need to clone a structure such as plist or alist.
-
-          (let* ((a (list (list 1))) (b (-clone a))) (setcar (car a) 2) b)
-              ⇒ ((1))
-
-\1f
-File: dash.info,  Node: Threading macros,  Next: Binding,  Prev: Tree operations,  Up: Functions
-
-2.12 Threading macros
-=====================
-
-Macros that conditionally combine sequential forms for brevity or
-readability.
-
- -- Macro: -> (x &optional form &rest more)
-     Thread the expr through the forms.  Insert X as the second item in
-     the first form, making a list of it if it is not a list already.
-     If there are more forms, insert the first form as the second item
-     in second form, etc.
-
-          (-> '(2 3 5))
-              ⇒ (2 3 5)
-          (-> '(2 3 5) (append '(8 13)))
-              ⇒ (2 3 5 8 13)
-          (-> '(2 3 5) (append '(8 13)) (-slice 1 -1))
-              ⇒ (3 5 8)
-
- -- Macro: ->> (x &optional form &rest more)
-     Thread the expr through the forms.  Insert X as the last item in
-     the first form, making a list of it if it is not a list already.
-     If there are more forms, insert the first form as the last item in
-     second form, etc.
-
-          (->> '(1 2 3) (-map 'square))
-              ⇒ (1 4 9)
-          (->> '(1 2 3) (-map 'square) (-remove 'even?))
-              ⇒ (1 9)
-          (->> '(1 2 3) (-map 'square) (-reduce '+))
-              ⇒ 14
-
- -- Macro: --> (x &rest forms)
-     Starting with the value of X, thread each expression through FORMS.
-
-     Insert X at the position signified by the symbol ‘it’ in the first
-     form.  If there are more forms, insert the first form at the
-     position signified by ‘it’ in the second form, etc.
-
-          (--> "def" (concat "abc" it "ghi"))
-              ⇒ "abcdefghi"
-          (--> "def" (concat "abc" it "ghi") (upcase it))
-              ⇒ "ABCDEFGHI"
-          (--> "def" (concat "abc" it "ghi") upcase)
-              ⇒ "ABCDEFGHI"
-
- -- Macro: -as-> (value variable &rest forms)
-     Starting with VALUE, thread VARIABLE through FORMS.
-
-     In the first form, bind VARIABLE to VALUE.  In the second form,
-     bind VARIABLE to the result of the first form, and so forth.
-
-          (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var))
-              ⇒ (8)
-          (-as-> 3 my-var 1+)
-              ⇒ 4
-          (-as-> 3 my-var)
-              ⇒ 3
-
- -- Macro: -some-> (x &optional form &rest more)
-     When expr is non-‘nil’, thread it through the first form (via ‘->’
-     (*note ->::)), and when that result is non-‘nil’, through the next
-     form, etc.
-
-          (-some-> '(2 3 5))
-              ⇒ (2 3 5)
-          (-some-> 5 square)
-              ⇒ 25
-          (-some-> 5 even? square)
-              ⇒ nil
-
- -- Macro: -some->> (x &optional form &rest more)
-     When expr is non-‘nil’, thread it through the first form (via ‘->>’
-     (*note ->>::)), and when that result is non-‘nil’, through the next
-     form, etc.
-
-          (-some->> '(1 2 3) (-map 'square))
-              ⇒ (1 4 9)
-          (-some->> '(1 3 5) (-last 'even?) (+ 100))
-              ⇒ nil
-          (-some->> '(2 4 6) (-last 'even?) (+ 100))
-              ⇒ 106
-
- -- Macro: -some--> (expr &rest forms)
-     Thread EXPR through FORMS via ‘-->’ (*note -->::), while the result
-     is non-‘nil’.  When EXPR evaluates to non-‘nil’, thread the result
-     through the first of FORMS, and when that result is non-‘nil’,
-     thread it through the next form, etc.
-
-          (-some--> "def" (concat "abc" it "ghi"))
-              ⇒ "abcdefghi"
-          (-some--> nil (concat "abc" it "ghi"))
-              ⇒ nil
-          (-some--> '(0 1) (-remove #'natnump it) (append it it) (-map #'1+ it))
-              ⇒ ()
-
- -- Macro: -doto (init &rest forms)
-     Evaluate INIT and pass it as argument to FORMS with ‘->’ (*note
-     ->::).  The RESULT of evaluating INIT is threaded through each of
-     FORMS individually using ‘->’ (*note ->::), which see.  The return
-     value is RESULT, which FORMS may have modified by side effect.
-
-          (-doto (list 1 2 3) pop pop)
-              ⇒ (3)
-          (-doto (cons 1 2) (setcar 3) (setcdr 4))
-              ⇒ (3 . 4)
-          (gethash 'k (--doto (make-hash-table) (puthash 'k 'v it)))
-              ⇒ v
-
-\1f
-File: dash.info,  Node: Binding,  Next: Side effects,  Prev: Threading macros,  Up: Functions
-
-2.13 Binding
-============
-
-Macros that combine ‘let’ and ‘let*’ with destructuring and flow
-control.
-
- -- Macro: -when-let ((var val) &rest body)
-     If VAL evaluates to non-‘nil’, bind it to VAR and execute body.
-
-     Note: binding is done according to ‘-let’ (*note -let::).
-
-          (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2))
-              ⇒ 5
-          (-when-let ((&plist :foo foo) (list :foo "foo")) foo)
-              ⇒ "foo"
-          (-when-let ((&plist :foo foo) (list :bar "bar")) foo)
-              ⇒ nil
-
- -- Macro: -when-let* (vars-vals &rest body)
-     If all VALS evaluate to true, bind them to their corresponding VARS
-     and execute body.  VARS-VALS should be a list of (VAR VAL) pairs.
-
-     Note: binding is done according to ‘-let*’ (*note -let*::).  VALS
-     are evaluated sequentially, and evaluation stops after the first
-     ‘nil’ VAL is encountered.
-
-          (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z))
-              ⇒ 15
-          (-when-let* ((x 5) (y nil) (z 7)) (+ x y z))
-              ⇒ nil
-
- -- Macro: -if-let ((var val) then &rest else)
-     If VAL evaluates to non-‘nil’, bind it to VAR and do THEN,
-     otherwise do ELSE.
-
-     Note: binding is done according to ‘-let’ (*note -let::).
-
-          (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7)
-              ⇒ 7
-          (--if-let (even? 4) it nil)
-              ⇒ t
-
- -- Macro: -if-let* (vars-vals then &rest else)
-     If all VALS evaluate to true, bind them to their corresponding VARS
-     and do THEN, otherwise do ELSE.  VARS-VALS should be a list of (VAR
-     VAL) pairs.
-
-     Note: binding is done according to ‘-let*’ (*note -let*::).  VALS
-     are evaluated sequentially, and evaluation stops after the first
-     ‘nil’ VAL is encountered.
-
-          (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo")
-              ⇒ 15
-          (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo")
-              ⇒ "foo"
-          (-if-let* (((_ _ x) '(nil nil 7))) x)
-              ⇒ 7
-
- -- Macro: -let (varlist &rest body)
-     Bind variables according to VARLIST then eval BODY.
-
-     VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
-     PATTERN is matched against the SOURCE "structurally".  SOURCE is
-     only evaluated once for each PATTERN.  Each PATTERN is matched
-     recursively, and can therefore contain sub-patterns which are
-     matched against corresponding sub-expressions of SOURCE.
-
-     All the SOURCEs are evalled before any symbols are bound (i.e.  "in
-     parallel").
-
-     If VARLIST only contains one (PATTERN SOURCE) element, you can
-     optionally specify it using a vector and discarding the outer-most
-     parens.  Thus
-
-     (-let ((PATTERN SOURCE)) ...)
-
-     becomes
-
-     (-let [PATTERN SOURCE] ...).
-
-     ‘-let’ (*note -let::) uses a convention of not binding places
-     (symbols) starting with _ whenever it’s possible.  You can use this
-     to skip over entries you don’t care about.  However, this is not
-     *always* possible (as a result of implementation) and these symbols
-     might get bound to undefined values.
-
-     Following is the overview of supported patterns.  Remember that
-     patterns can be matched recursively, so every a, b, aK in the
-     following can be a matching construct and not necessarily a
-     symbol/variable.
-
-     Symbol:
-
-     a - bind the SOURCE to A.  This is just like regular ‘let’.
-
-     Conses and lists:
-
-     (a) - bind ‘car’ of cons/list to A
-
-     (a .  b) - bind car of cons to A and ‘cdr’ to B
-
-     (a b) - bind car of list to A and ‘cadr’ to B
-
-     (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to
-     A3...
-
-     (a1 a2 a3 ... aN .  rest) - as above, but bind the Nth cdr to REST.
-
-     Vectors:
-
-     [a] - bind 0th element of a non-list sequence to A (works with
-     vectors, strings, bit arrays...)
-
-     [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st
-     to A1, 2nd to A2, ...  If the PATTERN is shorter than SOURCE, the
-     values at places not in PATTERN are ignored.  If the PATTERN is
-     longer than SOURCE, an ‘error’ is thrown.
-
-     [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the
-     sequence to REST.  This is conceptually the same as improper list
-     matching (a1 a2 ... aN .  rest)
-
-     Key/value stores:
-
-     (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
-     SOURCE plist to aK. If the value is not found, aK is ‘nil’.  Uses
-     ‘plist-get’ to fetch values.
-
-     (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the
-     SOURCE alist to aK. If the value is not found, aK is ‘nil’.  Uses
-     ‘assoc’ to fetch values.
-
-     (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the
-     SOURCE hash table to aK. If the value is not found, aK is ‘nil’.
-     Uses ‘gethash’ to fetch values.
-
-     Further, special keyword &keys supports "inline" matching of
-     plist-like key-value pairs, similarly to &keys keyword of
-     ‘cl-defun’.
-
-     (a1 a2 ... aN &keys key1 b1 ... keyN bK)
-
-     This binds N values from the list to a1 ... aN, then interprets the
-     cdr as a plist (see key/value matching above).
-
-     A shorthand notation for kv-destructuring exists which allows the
-     patterns be optionally left out and derived from the key name in
-     the following fashion:
-
-     - a key :foo is converted into ‘foo’ pattern, - a key ’bar is
-     converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’
-     pattern.
-
-     That is, the entire value under the key is bound to the derived
-     variable without any further destructuring.
-
-     This is possible only when the form following the key is not a
-     valid pattern (i.e.  not a symbol, a cons cell or a vector).
-     Otherwise the matching proceeds as usual and in case of an invalid
-     spec fails with an error.
-
-     Thus the patterns are normalized as follows:
-
-     ;; derive all the missing patterns (&plist :foo ’bar "baz") =>
-     (&plist :foo foo ’bar bar "baz" baz)
-
-     ;; we can specify some but not others (&plist :foo ’bar
-     explicit-bar) => (&plist :foo foo ’bar explicit-bar)
-
-     ;; nothing happens, we store :foo in x (&plist :foo x) => (&plist
-     :foo x)
-
-     ;; nothing happens, we match recursively (&plist :foo (a b c)) =>
-     (&plist :foo (a b c))
-
-     You can name the source using the syntax SYMBOL &as PATTERN.  This
-     syntax works with lists (proper or improper), vectors and all types
-     of maps.
-
-     (list &as a b c) (list 1 2 3)
-
-     binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
-
-     Similarly:
-
-     (bounds &as beg .  end) (cons 1 2)
-
-     binds BEG to 1, END to 2 and BOUNDS to (1 .  2).
-
-     (items &as first .  rest) (list 1 2 3)
-
-     binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
-
-     [vect &as _ b c] [1 2 3]
-
-     binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as
-     usual).
-
-     (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
-
-     binds B to 2 and PLIST to (:a 1 :b 2 :c 3).  Same for &alist and
-     &hash.
-
-     This is especially useful when we want to capture the result of a
-     computation and destructure at the same time.  Consider the form
-     (function-returning-complex-structure) returning a list of two
-     vectors with two items each.  We want to capture this entire result
-     and pass it to another computation, but at the same time we want to
-     get the second item from each vector.  We can achieve it with
-     pattern
-
-     (result &as [_ a] [_ b]) (function-returning-complex-structure)
-
-     Note: Clojure programmers may know this feature as the ":as
-     binding".  The difference is that we put the &as at the front
-     because we need to support improper list binding.
-
-          (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d))
-              ⇒ (1 2 3 4)
-          (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d))
-              ⇒ (1 2 3 (4 5 6))
-          (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar))
-              ⇒ (1 2)
-
- -- Macro: -let* (varlist &rest body)
-     Bind variables according to VARLIST then eval BODY.
-
-     VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
-     PATTERN is matched against the SOURCE structurally.  SOURCE is only
-     evaluated once for each PATTERN.
-
-     Each SOURCE can refer to the symbols already bound by this VARLIST.
-     This is useful if you want to destructure SOURCE recursively but
-     also want to name the intermediate structures.
-
-     See ‘-let’ (*note -let::) for the list of all possible patterns.
-
-          (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d))
-              ⇒ (1 2 3 4)
-          (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d))
-              ⇒ (1 (2 . 3) 2 3)
-          (-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar))
-              ⇒ (1 a b c (a b c))
-
- -- Macro: -lambda (match-form &rest body)
-     Return a lambda which destructures its input as MATCH-FORM and
-     executes BODY.
-
-     Note that you have to enclose the MATCH-FORM in a pair of parens,
-     such that:
-
-     (-lambda (x) body) (-lambda (x y ...) body)
-
-     has the usual semantics of ‘lambda’.  Furthermore, these get
-     translated into normal ‘lambda’, so there is no performance
-     penalty.
-
-     See ‘-let’ (*note -let::) for a description of the destructuring
-     mechanism.
-
-          (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6)))
-              ⇒ (3 7 11)
-          (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6]))
-              ⇒ (3 7 11)
-          (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6))
-              ⇒ (2 3 5 6)
-
- -- Macro: -setq ([match-form val] ...)
-     Bind each MATCH-FORM to the value of its VAL.
-
-     MATCH-FORM destructuring is done according to the rules of ‘-let’
-     (*note -let::).
-
-     This macro allows you to bind multiple variables by destructuring
-     the value, so for example:
-
-     (-setq (a b) x (&plist :c c) plist)
-
-     expands roughly speaking to the following code
-
-     (setq a (car x) b (cadr x) c (plist-get plist :c))
-
-     Care is taken to only evaluate each VAL once so that in case of
-     multiple assignments it does not cause unexpected side effects.
-
-          (let (a) (-setq a 1) a)
-              ⇒ 1
-          (let (a b) (-setq (a b) (list 1 2)) (list a b))
-              ⇒ (1 2)
-          (let (c) (-setq (&plist :c c) (list :c "c")) c)
-              ⇒ "c"
-
-\1f
-File: dash.info,  Node: Side effects,  Next: Destructive operations,  Prev: Binding,  Up: Functions
-
-2.14 Side effects
-=================
-
-Functions iterating over lists for side effect only.
-
- -- Function: -each (list fn)
-     Call FN on each element of LIST.  Return ‘nil’; this function is
-     intended for side effects.
-
-     Its anaphoric counterpart is ‘--each’.
-
-     For access to the current element’s index in LIST, see
-     ‘-each-indexed’ (*note -each-indexed::).
-
-          (let (l) (-each '(1 2 3) (lambda (x) (push x l))) l)
-              ⇒ (3 2 1)
-          (let (l) (--each '(1 2 3) (push it l)) l)
-              ⇒ (3 2 1)
-          (-each '(1 2 3) #'identity)
-              ⇒ nil
-
- -- Function: -each-while (list pred fn)
-     Call FN on each ITEM in LIST, while (PRED ITEM) is non-‘nil’.  Once
-     an ITEM is reached for which PRED returns ‘nil’, FN is no longer
-     called.  Return ‘nil’; this function is intended for side effects.
-
-     Its anaphoric counterpart is ‘--each-while’.
-
-          (let (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l)
-              ⇒ (4 2)
-          (let (l) (--each-while '(1 2 3 4) (< it 3) (push it l)) l)
-              ⇒ (2 1)
-          (let ((s 0)) (--each-while '(1 3 4 5) (< it 5) (setq s (+ s it))) s)
-              ⇒ 8
-
- -- Function: -each-indexed (list fn)
-     Call FN on each index and element of LIST.  For each ITEM at INDEX
-     in LIST, call (funcall FN INDEX ITEM).  Return ‘nil’; this function
-     is intended for side effects.
-
-     See also: ‘-map-indexed’ (*note -map-indexed::).
-
-          (let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l)
-              ⇒ ((c 2) (b 1) (a 0))
-          (let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l)
-              ⇒ ((c 2) (b 1) (a 0))
-          (let (l) (--each-indexed () (push it l)) l)
-              ⇒ ()
-
- -- Function: -each-r (list fn)
-     Call FN on each element of LIST in reversed order.  Return ‘nil’;
-     this function is intended for side effects.
-
-     Its anaphoric counterpart is ‘--each-r’.
-
-          (let (l) (-each-r '(1 2 3) (lambda (x) (push x l))) l)
-              ⇒ (1 2 3)
-          (let (l) (--each-r '(1 2 3) (push it l)) l)
-              ⇒ (1 2 3)
-          (-each-r '(1 2 3) #'identity)
-              ⇒ nil
-
- -- Function: -each-r-while (list pred fn)
-     Call FN on each ITEM in reversed LIST, while (PRED ITEM) is
-     non-‘nil’.  Once an ITEM is reached for which PRED returns ‘nil’,
-     FN is no longer called.  Return ‘nil’; this function is intended
-     for side effects.
-
-     Its anaphoric counterpart is ‘--each-r-while’.
-
-          (let (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l)
-              ⇒ (6)
-          (let (l) (--each-r-while '(1 2 3 4) (>= it 3) (push it l)) l)
-              ⇒ (3 4)
-          (let ((s 0)) (--each-r-while '(1 2 3 5) (> it 1) (setq s (+ s it))) s)
-              ⇒ 10
-
- -- Function: -dotimes (num fn)
-     Call FN NUM times, presumably for side effects.  FN is called with
-     a single argument on successive integers running from 0, inclusive,
-     to NUM, exclusive.  FN is not called if NUM is less than 1.
-
-     This function’s anaphoric counterpart is ‘--dotimes’.
-
-          (let (s) (-dotimes 3 (lambda (n) (push n s))) s)
-              ⇒ (2 1 0)
-          (let (s) (-dotimes 0 (lambda (n) (push n s))) s)
-              ⇒ ()
-          (let (s) (--dotimes 5 (push it s)) s)
-              ⇒ (4 3 2 1 0)
-
-\1f
-File: dash.info,  Node: Destructive operations,  Next: Function combinators,  Prev: Side effects,  Up: Functions
-
-2.15 Destructive operations
-===========================
-
-Macros that modify variables holding lists.
-
- -- Macro: !cons (car cdr)
-     Destructive: Set CDR to the cons of CAR and CDR.
-
-          (let (l) (!cons 5 l) l)
-              ⇒ (5)
-          (let ((l '(3))) (!cons 5 l) l)
-              ⇒ (5 3)
-
- -- Macro: !cdr (list)
-     Destructive: Set LIST to the cdr of LIST.
-
-          (let ((l '(3))) (!cdr l) l)
-              ⇒ ()
-          (let ((l '(3 5))) (!cdr l) l)
-              ⇒ (5)
-
-\1f
-File: dash.info,  Node: Function combinators,  Prev: Destructive operations,  Up: Functions
-
-2.16 Function combinators
-=========================
-
-Functions that manipulate and compose other functions.
-
- -- Function: -partial (fun &rest args)
-     Return a function that is a partial application of FUN to ARGS.
-     ARGS is a list of the first N arguments to pass to FUN.  The result
-     is a new function which does the same as FUN, except that the first
-     N arguments are fixed at the values with which this function was
-     called.
-
-          (funcall (-partial #'+ 5))
-              ⇒ 5
-          (funcall (-partial #'- 5) 3)
-              ⇒ 2
-          (funcall (-partial #'+ 5 2) 3)
-              ⇒ 10
-
- -- Function: -rpartial (fn &rest args)
-     Return a function that is a partial application of FN to ARGS.
-     ARGS is a list of the last N arguments to pass to FN.  The result
-     is a new function which does the same as FN, except that the last N
-     arguments are fixed at the values with which this function was
-     called.  This is like ‘-partial’ (*note -partial::), except the
-     arguments are fixed starting from the right rather than the left.
-
-          (funcall (-rpartial #'- 5))
-              ⇒ -5
-          (funcall (-rpartial #'- 5) 8)
-              ⇒ 3
-          (funcall (-rpartial #'- 5 2) 10)
-              ⇒ 3
-
- -- Function: -juxt (&rest fns)
-     Return a function that is the juxtaposition of FNS.  The returned
-     function takes a variable number of ARGS, applies each of FNS in
-     turn to ARGS, and returns the list of results.
-
-          (funcall (-juxt) 1 2)
-              ⇒ ()
-          (funcall (-juxt #'+ #'- #'* #'/) 7 5)
-              ⇒ (12 2 35 1)
-          (mapcar (-juxt #'number-to-string #'1+) '(1 2))
-              ⇒ (("1" 2) ("2" 3))
-
- -- Function: -compose (&rest fns)
-     Compose FNS into a single composite function.  Return a function
-     that takes a variable number of ARGS, applies the last function in
-     FNS to ARGS, and returns the result of calling each remaining
-     function on the result of the previous function, right-to-left.  If
-     no FNS are given, return a variadic ‘identity’ function.
-
-          (funcall (-compose #'- #'1+ #'+) 1 2 3)
-              ⇒ -7
-          (funcall (-compose #'identity #'1+) 3)
-              ⇒ 4
-          (mapcar (-compose #'not #'stringp) '(nil ""))
-              ⇒ (t nil)
-
- -- Function: -applify (fn)
-     Return a function that applies FN to a single list of args.  This
-     changes the arity of FN from taking N distinct arguments to taking
-     1 argument which is a list of N arguments.
-
-          (funcall (-applify #'+) nil)
-              ⇒ 0
-          (mapcar (-applify #'+) '((1 1 1) (1 2 3) (5 5 5)))
-              ⇒ (3 6 15)
-          (funcall (-applify #'<) '(3 6))
-              ⇒ t
-
- -- Function: -on (op trans)
-     Return a function that calls TRANS on each arg and OP on the
-     results.  The returned function takes a variable number of
-     arguments, calls the function TRANS on each one in turn, and then
-     passes those results as the list of arguments to OP, in the same
-     order.
-
-     For example, the following pairs of expressions are morally
-     equivalent:
-
-     (funcall (-on #’+ #’1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3)) (funcall
-     (-on #’+ #’1+)) = (+)
-
-          (-sort (-on #'< #'length) '((1 2 3) (1) (1 2)))
-              ⇒ ((1) (1 2) (1 2 3))
-          (funcall (-on #'min #'string-to-number) "22" "2" "1" "12")
-              ⇒ 1
-          (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2)))
-              ⇒ (4)
-
- -- Function: -flip (fn)
-     Return a function that calls FN with its arguments reversed.  The
-     returned function takes the same number of arguments as FN.
-
-     For example, the following two expressions are morally equivalent:
-
-     (funcall (-flip #’-) 1 2) = (- 2 1)
-
-     See also: ‘-rotate-args’ (*note -rotate-args::).
-
-          (-sort (-flip #'<) '(4 3 6 1))
-              ⇒ (6 4 3 1)
-          (funcall (-flip #'-) 3 2 1 10)
-              ⇒ 4
-          (funcall (-flip #'1+) 1)
-              ⇒ 2
-
- -- Function: -rotate-args (n fn)
-     Return a function that calls FN with args rotated N places to the
-     right.  The returned function takes the same number of arguments as
-     FN, rotates the list of arguments N places to the right (left if N
-     is negative) just like ‘-rotate’ (*note -rotate::), and applies FN
-     to the result.
-
-     See also: ‘-flip’ (*note -flip::).
-
-          (funcall (-rotate-args -1 #'list) 1 2 3 4)
-              ⇒ (2 3 4 1)
-          (funcall (-rotate-args 1 #'-) 1 10 100)
-              ⇒ 89
-          (funcall (-rotate-args 2 #'list) 3 4 5 1 2)
-              ⇒ (1 2 3 4 5)
-
- -- Function: -const (c)
-     Return a function that returns C ignoring any additional arguments.
-
-     In types: a -> b -> a
-
-          (funcall (-const 2) 1 3 "foo")
-              ⇒ 2
-          (mapcar (-const 1) '("a" "b" "c" "d"))
-              ⇒ (1 1 1 1)
-          (-sum (mapcar (-const 1) '("a" "b" "c" "d")))
-              ⇒ 4
-
- -- Macro: -cut (&rest params)
-     Take n-ary function and n arguments and specialize some of them.
-     Arguments denoted by <> will be left unspecialized.
-
-     See SRFI-26 for detailed description.
-
-          (funcall (-cut list 1 <> 3 <> 5) 2 4)
-              ⇒ (1 2 3 4 5)
-          (-map (-cut funcall <> 5) `(1+ 1- ,(lambda (x) (/ 1.0 x))))
-              ⇒ (6 4 0.2)
-          (-map (-cut <> 1 2 3) '(list vector string))
-              ⇒ ((1 2 3) [1 2 3] "\1\2\3")
-
- -- Function: -not (pred)
-     Return a predicate that negates the result of PRED.  The returned
-     predicate passes its arguments to PRED.  If PRED returns ‘nil’, the
-     result is non-‘nil’; otherwise the result is ‘nil’.
-
-     See also: ‘-andfn’ (*note -andfn::) and ‘-orfn’ (*note -orfn::).
-
-          (funcall (-not #'numberp) "5")
-              ⇒ t
-          (-sort (-not #'<) '(5 2 1 0 6))
-              ⇒ (6 5 2 1 0)
-          (-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8))
-              ⇒ (1 2 3 4)
-
- -- Function: -orfn (&rest preds)
-     Return a predicate that returns the first non-‘nil’ result of
-     PREDS.  The returned predicate takes a variable number of
-     arguments, passes them to each predicate in PREDS in turn until one
-     of them returns non-‘nil’, and returns that non-‘nil’ result
-     without calling the remaining PREDS.  If all PREDS return ‘nil’, or
-     if no PREDS are given, the returned predicate returns ‘nil’.
-
-     See also: ‘-andfn’ (*note -andfn::) and ‘-not’ (*note -not::).
-
-          (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t))
-              ⇒ (1 nil t)
-          (funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe")
-              ⇒ 1
-          (funcall (-orfn #'= #'+) 1 1)
-              ⇒ t
-
- -- Function: -andfn (&rest preds)
-     Return a predicate that returns non-‘nil’ if all PREDS do so.  The
-     returned predicate P takes a variable number of arguments and
-     passes them to each predicate in PREDS in turn.  If any one of
-     PREDS returns ‘nil’, P also returns ‘nil’ without calling the
-     remaining PREDS.  If all PREDS return non-‘nil’, P returns the last
-     such value.  If no PREDS are given, P always returns non-‘nil’.
-
-     See also: ‘-orfn’ (*note -orfn::) and ‘-not’ (*note -not::).
-
-          (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2))
-              ⇒ (1 2)
-          (mapcar (-andfn #'numberp #'1+) '(a 1 b 6))
-              ⇒ (nil 2 nil 7)
-          (funcall (-andfn #'= #'+) 1 1)
-              ⇒ 2
-
- -- Function: -iteratefn (fn n)
-     Return a function FN composed N times with itself.
-
-     FN is a unary function.  If you need to use a function of higher
-     arity, use ‘-applify’ (*note -applify::) first to turn it into a
-     unary function.
-
-     With n = 0, this acts as identity function.
-
-     In types: (a -> a) -> Int -> a -> a.
-
-     This function satisfies the following law:
-
-     (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init
-     (1+ n))).
-
-          (funcall (-iteratefn (lambda (x) (* x x)) 3) 2)
-              ⇒ 256
-          (funcall (-iteratefn '1+ 3) 1)
-              ⇒ 4
-          (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5))
-              ⇒ (4 5)
-
- -- Function: -fixfn (fn &optional equal-test halt-test)
-     Return a function that computes the (least) fixpoint of FN.
-
-     FN must be a unary function.  The returned lambda takes a single
-     argument, X, the initial value for the fixpoint iteration.  The
-     iteration halts when either of the following conditions is
-     satisfied:
-
-     1.  Iteration converges to the fixpoint, with equality being tested
-     using EQUAL-TEST.  If EQUAL-TEST is not specified, ‘equal’ is used.
-     For functions over the floating point numbers, it may be necessary
-     to provide an appropriate approximate comparison test.
-
-     2.  HALT-TEST returns a non-‘nil’ value.  HALT-TEST defaults to a
-     simple counter that returns ‘t’ after ‘-fixfn-max-iterations’, to
-     guard against infinite iteration.  Otherwise, HALT-TEST must be a
-     function that accepts a single argument, the current value of X,
-     and returns non-‘nil’ as long as iteration should continue.  In
-     this way, a more sophisticated convergence test may be supplied by
-     the caller.
-
-     The return value of the lambda is either the fixpoint or, if
-     iteration halted before converging, a cons with car ‘halted’ and
-     cdr the final output from HALT-TEST.
-
-     In types: (a -> a) -> a -> a.
-
-          (funcall (-fixfn #'cos #'approx=) 0.7)
-              ⇒ 0.7390851332151607
-          (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0)
-              ⇒ 1.8555845286409378
-          (funcall (-fixfn #'sin #'approx=) 0.1)
-              ⇒ (halted . t)
-
- -- Function: -prodfn (&rest fns)
-     Return a function that applies each of FNS to each of a list of
-     arguments.
-
-     Takes a list of N functions and returns a function that takes a
-     list of length N, applying Ith function to Ith element of the input
-     list.  Returns a list of length N.
-
-     In types (for N=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d)
-
-     This function satisfies the following laws:
-
-     (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn
-     (-compose f f’) (-compose g g’) ...)
-
-     (-prodfn f g ...) = (-juxt (-compose f (-partial #’nth 0))
-     (-compose g (-partial #’nth 1)) ...)
-
-     (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose f
-     f’) (-compose g g’) ...)
-
-     (-compose (-partial #’nth n) (-prod f1 f2 ...)) = (-compose fn
-     (-partial #’nth n))
-
-          (funcall (-prodfn #'1+ #'1- #'number-to-string) '(1 2 3))
-              ⇒ (2 1 "3")
-          (-map (-prodfn #'1- #'1+) '((1 2) (3 4) (5 6)))
-              ⇒ ((0 3) (2 5) (4 7))
-          (apply #'+ (funcall (-prodfn #'length #'string-to-number) '((t) "5")))
-              ⇒ 6
-
-\1f
-File: dash.info,  Node: Development,  Next: FDL,  Prev: Functions,  Up: Top
-
-3 Development
-*************
-
-The Dash repository is hosted on GitHub at
-<https://github.com/magnars/dash.el>.
-
-* Menu:
-
-* Contribute::          How to contribute.
-* Contributors::        List of contributors.
-
-\1f
-File: dash.info,  Node: Contribute,  Next: Contributors,  Up: Development
-
-3.1 Contribute
-==============
-
-Yes, please do.  Pure functions in the list manipulation realm only,
-please.  There’s a suite of examples/tests in ‘dev/examples.el’, so
-remember to add tests for your additions, or they may get broken later.
-
-   Run the tests with ‘make check’.  Regenerate the docs with ‘make
-docs’.  Contributors are encouraged to install these commands as a Git
-pre-commit hook, so that the tests are always running and the docs are
-always in sync:
-
-     $ cp dev/pre-commit.sh .git/hooks/pre-commit
-
-   Oh, and don’t edit ‘README.md’ or ‘dash.texi’ directly, as they are
-auto-generated.  Instead, change their respective templates
-‘readme-template.md’ or ‘dash-template.texi’.
-
-   To ensure that Dash can be distributed with GNU ELPA or Emacs, we
-require that all contributors assign copyright to the Free Software
-Foundation.  For more on this, *note (emacs)Copyright Assignment::.
-
-\1f
-File: dash.info,  Node: Contributors,  Prev: Contribute,  Up: Development
-
-3.2 Contributors
-================
-
-   • Matus Goljer (https://github.com/Fuco1) contributed lots of
-     features and functions.
-   • Takafumi Arakaki (https://github.com/tkf) contributed ‘-group-by’.
-   • tali713 (https://github.com/tali713) is the author of ‘-applify’.
-   • Víctor M. Valenzuela (https://github.com/vemv) contributed
-     ‘-repeat’.
-   • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’.
-   • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’,
-     ‘-first-item’, and ‘-last-item’.
-   • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’,
-     ‘-when-let’, and ‘-insert-at’.
-   • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’,
-     ‘-product’, and ‘-same-items?’.
-   • Christina Whyte (https://github.com/kurisuwhyte) contributed
-     ‘-compose’.
-   • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’,
-     ‘-pad’, ‘-annotate’, ‘-zip-fill’, and a variadic version of ‘-zip’.
-   • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’
-     family use ‘-let’ destructuring and improved the script for
-     generating documentation.
-   • Mark Oteiza (https://github.com/holomorph) contributed ‘-iota’ and
-     the script to create an Info manual.
-   • Vasilij Schneidermann (https://github.com/wasamasa) contributed
-     ‘-some’.
-   • William West (https://github.com/occidens) made ‘-fixfn’ more
-     robust at handling floats.
-   • Cam Saul (https://github.com/camsaul) contributed ‘-some->’,
-     ‘-some->>’, and ‘-some-->’.
-   • Basil L. Contovounesios (https://github.com/basil-conto)
-     contributed ‘-common-prefix’, ‘-common-suffix’, and various other
-     improvements.
-   • Paul Pogonyshev (https://github.com/doublep) contributed ‘-each-r’
-     and ‘-each-r-while’.
-
-   Thanks!
-
-   New contributors are very welcome.  *Note Contribute::.
-
-\1f
-File: dash.info,  Node: FDL,  Next: GPL,  Prev: Development,  Up: Top
-
-Appendix A GNU Free Documentation License
-*****************************************
-
-                     Version 1.3, 3 November 2008
-
-     Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
-     <https://fsf.org/>
-
-     Everyone is permitted to copy and distribute verbatim copies
-     of this license document, but changing it is not allowed.
-
-  0. PREAMBLE
-
-     The purpose of this License is to make a manual, textbook, or other
-     functional and useful document “free” in the sense of freedom: to
-     assure everyone the effective freedom to copy and redistribute it,
-     with or without modifying it, either commercially or
-     noncommercially.  Secondarily, this License preserves for the
-     author and publisher a way to get credit for their work, while not
-     being considered responsible for modifications made by others.
-
-     This License is a kind of “copyleft”, which means that derivative
-     works of the document must themselves be free in the same sense.
-     It complements the GNU General Public License, which is a copyleft
-     license designed for free software.
-
-     We have designed this License in order to use it for manuals for
-     free software, because free software needs free documentation: a
-     free program should come with manuals providing the same freedoms
-     that the software does.  But this License is not limited to
-     software manuals; it can be used for any textual work, regardless
-     of subject matter or whether it is published as a printed book.  We
-     recommend this License principally for works whose purpose is
-     instruction or reference.
-
-  1. APPLICABILITY AND DEFINITIONS
-
-     This License applies to any manual or other work, in any medium,
-     that contains a notice placed by the copyright holder saying it can
-     be distributed under the terms of this License.  Such a notice
-     grants a world-wide, royalty-free license, unlimited in duration,
-     to use that work under the conditions stated herein.  The
-     “Document”, below, refers to any such manual or work.  Any member
-     of the public is a licensee, and is addressed as “you”.  You accept
-     the license if you copy, modify or distribute the work in a way
-     requiring permission under copyright law.
-
-     A “Modified Version” of the Document means any work containing the
-     Document or a portion of it, either copied verbatim, or with
-     modifications and/or translated into another language.
-
-     A “Secondary Section” is a named appendix or a front-matter section
-     of the Document that deals exclusively with the relationship of the
-     publishers or authors of the Document to the Document’s overall
-     subject (or to related matters) and contains nothing that could
-     fall directly within that overall subject.  (Thus, if the Document
-     is in part a textbook of mathematics, a Secondary Section may not
-     explain any mathematics.)  The relationship could be a matter of
-     historical connection with the subject or with related matters, or
-     of legal, commercial, philosophical, ethical or political position
-     regarding them.
-
-     The “Invariant Sections” are certain Secondary Sections whose
-     titles are designated, as being those of Invariant Sections, in the
-     notice that says that the Document is released under this License.
-     If a section does not fit the above definition of Secondary then it
-     is not allowed to be designated as Invariant.  The Document may
-     contain zero Invariant Sections.  If the Document does not identify
-     any Invariant Sections then there are none.
-
-     The “Cover Texts” are certain short passages of text that are
-     listed, as Front-Cover Texts or Back-Cover Texts, in the notice
-     that says that the Document is released under this License.  A
-     Front-Cover Text may be at most 5 words, and a Back-Cover Text may
-     be at most 25 words.
-
-     A “Transparent” copy of the Document means a machine-readable copy,
-     represented in a format whose specification is available to the
-     general public, that is suitable for revising the document
-     straightforwardly with generic text editors or (for images composed
-     of pixels) generic paint programs or (for drawings) some widely
-     available drawing editor, and that is suitable for input to text
-     formatters or for automatic translation to a variety of formats
-     suitable for input to text formatters.  A copy made in an otherwise
-     Transparent file format whose markup, or absence of markup, has
-     been arranged to thwart or discourage subsequent modification by
-     readers is not Transparent.  An image format is not Transparent if
-     used for any substantial amount of text.  A copy that is not
-     “Transparent” is called “Opaque”.
-
-     Examples of suitable formats for Transparent copies include plain
-     ASCII without markup, Texinfo input format, LaTeX input format,
-     SGML or XML using a publicly available DTD, and standard-conforming
-     simple HTML, PostScript or PDF designed for human modification.
-     Examples of transparent image formats include PNG, XCF and JPG.
-     Opaque formats include proprietary formats that can be read and
-     edited only by proprietary word processors, SGML or XML for which
-     the DTD and/or processing tools are not generally available, and
-     the machine-generated HTML, PostScript or PDF produced by some word
-     processors for output purposes only.
-
-     The “Title Page” means, for a printed book, the title page itself,
-     plus such following pages as are needed to hold, legibly, the
-     material this License requires to appear in the title page.  For
-     works in formats which do not have any title page as such, “Title
-     Page” means the text near the most prominent appearance of the
-     work’s title, preceding the beginning of the body of the text.
-
-     The “publisher” means any person or entity that distributes copies
-     of the Document to the public.
-
-     A section “Entitled XYZ” means a named subunit of the Document
-     whose title either is precisely XYZ or contains XYZ in parentheses
-     following text that translates XYZ in another language.  (Here XYZ
-     stands for a specific section name mentioned below, such as
-     “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.)
-     To “Preserve the Title” of such a section when you modify the
-     Document means that it remains a section “Entitled XYZ” according
-     to this definition.
-
-     The Document may include Warranty Disclaimers next to the notice
-     which states that this License applies to the Document.  These
-     Warranty Disclaimers are considered to be included by reference in
-     this License, but only as regards disclaiming warranties: any other
-     implication that these Warranty Disclaimers may have is void and
-     has no effect on the meaning of this License.
-
-  2. VERBATIM COPYING
-
-     You may copy and distribute the Document in any medium, either
-     commercially or noncommercially, provided that this License, the
-     copyright notices, and the license notice saying this License
-     applies to the Document are reproduced in all copies, and that you
-     add no other conditions whatsoever to those of this License.  You
-     may not use technical measures to obstruct or control the reading
-     or further copying of the copies you make or distribute.  However,
-     you may accept compensation in exchange for copies.  If you
-     distribute a large enough number of copies you must also follow the
-     conditions in section 3.
-
-     You may also lend copies, under the same conditions stated above,
-     and you may publicly display copies.
-
-  3. COPYING IN QUANTITY
-
-     If you publish printed copies (or copies in media that commonly
-     have printed covers) of the Document, numbering more than 100, and
-     the Document’s license notice requires Cover Texts, you must
-     enclose the copies in covers that carry, clearly and legibly, all
-     these Cover Texts: Front-Cover Texts on the front cover, and
-     Back-Cover Texts on the back cover.  Both covers must also clearly
-     and legibly identify you as the publisher of these copies.  The
-     front cover must present the full title with all words of the title
-     equally prominent and visible.  You may add other material on the
-     covers in addition.  Copying with changes limited to the covers, as
-     long as they preserve the title of the Document and satisfy these
-     conditions, can be treated as verbatim copying in other respects.
-
-     If the required texts for either cover are too voluminous to fit
-     legibly, you should put the first ones listed (as many as fit
-     reasonably) on the actual cover, and continue the rest onto
-     adjacent pages.
-
-     If you publish or distribute Opaque copies of the Document
-     numbering more than 100, you must either include a machine-readable
-     Transparent copy along with each Opaque copy, or state in or with
-     each Opaque copy a computer-network location from which the general
-     network-using public has access to download using public-standard
-     network protocols a complete Transparent copy of the Document, free
-     of added material.  If you use the latter option, you must take
-     reasonably prudent steps, when you begin distribution of Opaque
-     copies in quantity, to ensure that this Transparent copy will
-     remain thus accessible at the stated location until at least one
-     year after the last time you distribute an Opaque copy (directly or
-     through your agents or retailers) of that edition to the public.
-
-     It is requested, but not required, that you contact the authors of
-     the Document well before redistributing any large number of copies,
-     to give them a chance to provide you with an updated version of the
-     Document.
-
-  4. MODIFICATIONS
-
-     You may copy and distribute a Modified Version of the Document
-     under the conditions of sections 2 and 3 above, provided that you
-     release the Modified Version under precisely this License, with the
-     Modified Version filling the role of the Document, thus licensing
-     distribution and modification of the Modified Version to whoever
-     possesses a copy of it.  In addition, you must do these things in
-     the Modified Version:
-
-       A. Use in the Title Page (and on the covers, if any) a title
-          distinct from that of the Document, and from those of previous
-          versions (which should, if there were any, be listed in the
-          History section of the Document).  You may use the same title
-          as a previous version if the original publisher of that
-          version gives permission.
-
-       B. List on the Title Page, as authors, one or more persons or
-          entities responsible for authorship of the modifications in
-          the Modified Version, together with at least five of the
-          principal authors of the Document (all of its principal
-          authors, if it has fewer than five), unless they release you
-          from this requirement.
-
-       C. State on the Title page the name of the publisher of the
-          Modified Version, as the publisher.
-
-       D. Preserve all the copyright notices of the Document.
-
-       E. Add an appropriate copyright notice for your modifications
-          adjacent to the other copyright notices.
-
-       F. Include, immediately after the copyright notices, a license
-          notice giving the public permission to use the Modified
-          Version under the terms of this License, in the form shown in
-          the Addendum below.
-
-       G. Preserve in that license notice the full lists of Invariant
-          Sections and required Cover Texts given in the Document’s
-          license notice.
-
-       H. Include an unaltered copy of this License.
-
-       I. Preserve the section Entitled “History”, Preserve its Title,
-          and add to it an item stating at least the title, year, new
-          authors, and publisher of the Modified Version as given on the
-          Title Page.  If there is no section Entitled “History” in the
-          Document, create one stating the title, year, authors, and
-          publisher of the Document as given on its Title Page, then add
-          an item describing the Modified Version as stated in the
-          previous sentence.
-
-       J. Preserve the network location, if any, given in the Document
-          for public access to a Transparent copy of the Document, and
-          likewise the network locations given in the Document for
-          previous versions it was based on.  These may be placed in the
-          “History” section.  You may omit a network location for a work
-          that was published at least four years before the Document
-          itself, or if the original publisher of the version it refers
-          to gives permission.
-
-       K. For any section Entitled “Acknowledgements” or “Dedications”,
-          Preserve the Title of the section, and preserve in the section
-          all the substance and tone of each of the contributor
-          acknowledgements and/or dedications given therein.
-
-       L. Preserve all the Invariant Sections of the Document, unaltered
-          in their text and in their titles.  Section numbers or the
-          equivalent are not considered part of the section titles.
-
-       M. Delete any section Entitled “Endorsements”.  Such a section
-          may not be included in the Modified Version.
-
-       N. Do not retitle any existing section to be Entitled
-          “Endorsements” or to conflict in title with any Invariant
-          Section.
-
-       O. Preserve any Warranty Disclaimers.
-
-     If the Modified Version includes new front-matter sections or
-     appendices that qualify as Secondary Sections and contain no
-     material copied from the Document, you may at your option designate
-     some or all of these sections as invariant.  To do this, add their
-     titles to the list of Invariant Sections in the Modified Version’s
-     license notice.  These titles must be distinct from any other
-     section titles.
-
-     You may add a section Entitled “Endorsements”, provided it contains
-     nothing but endorsements of your Modified Version by various
-     parties—for example, statements of peer review or that the text has
-     been approved by an organization as the authoritative definition of
-     a standard.
-
-     You may add a passage of up to five words as a Front-Cover Text,
-     and a passage of up to 25 words as a Back-Cover Text, to the end of
-     the list of Cover Texts in the Modified Version.  Only one passage
-     of Front-Cover Text and one of Back-Cover Text may be added by (or
-     through arrangements made by) any one entity.  If the Document
-     already includes a cover text for the same cover, previously added
-     by you or by arrangement made by the same entity you are acting on
-     behalf of, you may not add another; but you may replace the old
-     one, on explicit permission from the previous publisher that added
-     the old one.
-
-     The author(s) and publisher(s) of the Document do not by this
-     License give permission to use their names for publicity for or to
-     assert or imply endorsement of any Modified Version.
-
-  5. COMBINING DOCUMENTS
-
-     You may combine the Document with other documents released under
-     this License, under the terms defined in section 4 above for
-     modified versions, provided that you include in the combination all
-     of the Invariant Sections of all of the original documents,
-     unmodified, and list them all as Invariant Sections of your
-     combined work in its license notice, and that you preserve all
-     their Warranty Disclaimers.
-
-     The combined work need only contain one copy of this License, and
-     multiple identical Invariant Sections may be replaced with a single
-     copy.  If there are multiple Invariant Sections with the same name
-     but different contents, make the title of each such section unique
-     by adding at the end of it, in parentheses, the name of the
-     original author or publisher of that section if known, or else a
-     unique number.  Make the same adjustment to the section titles in
-     the list of Invariant Sections in the license notice of the
-     combined work.
-
-     In the combination, you must combine any sections Entitled
-     “History” in the various original documents, forming one section
-     Entitled “History”; likewise combine any sections Entitled
-     “Acknowledgements”, and any sections Entitled “Dedications”.  You
-     must delete all sections Entitled “Endorsements.”
-
-  6. COLLECTIONS OF DOCUMENTS
-
-     You may make a collection consisting of the Document and other
-     documents released under this License, and replace the individual
-     copies of this License in the various documents with a single copy
-     that is included in the collection, provided that you follow the
-     rules of this License for verbatim copying of each of the documents
-     in all other respects.
-
-     You may extract a single document from such a collection, and
-     distribute it individually under this License, provided you insert
-     a copy of this License into the extracted document, and follow this
-     License in all other respects regarding verbatim copying of that
-     document.
-
-  7. AGGREGATION WITH INDEPENDENT WORKS
-
-     A compilation of the Document or its derivatives with other
-     separate and independent documents or works, in or on a volume of a
-     storage or distribution medium, is called an “aggregate” if the
-     copyright resulting from the compilation is not used to limit the
-     legal rights of the compilation’s users beyond what the individual
-     works permit.  When the Document is included in an aggregate, this
-     License does not apply to the other works in the aggregate which
-     are not themselves derivative works of the Document.
-
-     If the Cover Text requirement of section 3 is applicable to these
-     copies of the Document, then if the Document is less than one half
-     of the entire aggregate, the Document’s Cover Texts may be placed
-     on covers that bracket the Document within the aggregate, or the
-     electronic equivalent of covers if the Document is in electronic
-     form.  Otherwise they must appear on printed covers that bracket
-     the whole aggregate.
-
-  8. TRANSLATION
-
-     Translation is considered a kind of modification, so you may
-     distribute translations of the Document under the terms of section
-     4.  Replacing Invariant Sections with translations requires special
-     permission from their copyright holders, but you may include
-     translations of some or all Invariant Sections in addition to the
-     original versions of these Invariant Sections.  You may include a
-     translation of this License, and all the license notices in the
-     Document, and any Warranty Disclaimers, provided that you also
-     include the original English version of this License and the
-     original versions of those notices and disclaimers.  In case of a
-     disagreement between the translation and the original version of
-     this License or a notice or disclaimer, the original version will
-     prevail.
-
-     If a section in the Document is Entitled “Acknowledgements”,
-     “Dedications”, or “History”, the requirement (section 4) to
-     Preserve its Title (section 1) will typically require changing the
-     actual title.
-
-  9. TERMINATION
-
-     You may not copy, modify, sublicense, or distribute the Document
-     except as expressly provided under this License.  Any attempt
-     otherwise to copy, modify, sublicense, or distribute it is void,
-     and will automatically terminate your rights under this License.
-
-     However, if you cease all violation of this License, then your
-     license from a particular copyright holder is reinstated (a)
-     provisionally, unless and until the copyright holder explicitly and
-     finally terminates your license, and (b) permanently, if the
-     copyright holder fails to notify you of the violation by some
-     reasonable means prior to 60 days after the cessation.
-
-     Moreover, your license from a particular copyright holder is
-     reinstated permanently if the copyright holder notifies you of the
-     violation by some reasonable means, this is the first time you have
-     received notice of violation of this License (for any work) from
-     that copyright holder, and you cure the violation prior to 30 days
-     after your receipt of the notice.
-
-     Termination of your rights under this section does not terminate
-     the licenses of parties who have received copies or rights from you
-     under this License.  If your rights have been terminated and not
-     permanently reinstated, receipt of a copy of some or all of the
-     same material does not give you any rights to use it.
-
-  10. FUTURE REVISIONS OF THIS LICENSE
-
-     The Free Software Foundation may publish new, revised versions of
-     the GNU Free Documentation License from time to time.  Such new
-     versions will be similar in spirit to the present version, but may
-     differ in detail to address new problems or concerns.  See
-     <https://www.gnu.org/licenses/>.
-
-     Each version of the License is given a distinguishing version
-     number.  If the Document specifies that a particular numbered
-     version of this License “or any later version” applies to it, you
-     have the option of following the terms and conditions either of
-     that specified version or of any later version that has been
-     published (not as a draft) by the Free Software Foundation.  If the
-     Document does not specify a version number of this License, you may
-     choose any version ever published (not as a draft) by the Free
-     Software Foundation.  If the Document specifies that a proxy can
-     decide which future versions of this License can be used, that
-     proxy’s public statement of acceptance of a version permanently
-     authorizes you to choose that version for the Document.
-
-  11. RELICENSING
-
-     “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any
-     World Wide Web server that publishes copyrightable works and also
-     provides prominent facilities for anybody to edit those works.  A
-     public wiki that anybody can edit is an example of such a server.
-     A “Massive Multiauthor Collaboration” (or “MMC”) contained in the
-     site means any set of copyrightable works thus published on the MMC
-     site.
-
-     “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0
-     license published by Creative Commons Corporation, a not-for-profit
-     corporation with a principal place of business in San Francisco,
-     California, as well as future copyleft versions of that license
-     published by that same organization.
-
-     “Incorporate” means to publish or republish a Document, in whole or
-     in part, as part of another Document.
-
-     An MMC is “eligible for relicensing” if it is licensed under this
-     License, and if all works that were first published under this
-     License somewhere other than this MMC, and subsequently
-     incorporated in whole or in part into the MMC, (1) had no cover
-     texts or invariant sections, and (2) were thus incorporated prior
-     to November 1, 2008.
-
-     The operator of an MMC Site may republish an MMC contained in the
-     site under CC-BY-SA on the same site at any time before August 1,
-     2009, provided the MMC is eligible for relicensing.
-
-ADDENDUM: How to use this License for your documents
-====================================================
-
-To use this License in a document you have written, include a copy of
-the License in the document and put the following copyright and license
-notices just after the title page:
-
-       Copyright (C)  YEAR  YOUR NAME.
-       Permission is granted to copy, distribute and/or modify this document
-       under the terms of the GNU Free Documentation License, Version 1.3
-       or any later version published by the Free Software Foundation;
-       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
-       Texts.  A copy of the license is included in the section entitled ``GNU
-       Free Documentation License''.
-
-   If you have Invariant Sections, Front-Cover Texts and Back-Cover
-Texts, replace the “with...Texts.” line with this:
-
-         with the Invariant Sections being LIST THEIR TITLES, with
-         the Front-Cover Texts being LIST, and with the Back-Cover Texts
-         being LIST.
-
-   If you have Invariant Sections without Cover Texts, or some other
-combination of the three, merge those two alternatives to suit the
-situation.
-
-   If your document contains nontrivial examples of program code, we
-recommend releasing these examples in parallel under your choice of free
-software license, such as the GNU General Public License, to permit
-their use in free software.
-
-\1f
-File: dash.info,  Node: GPL,  Next: Index,  Prev: FDL,  Up: Top
-
-Appendix B GNU General Public License
-*************************************
-
-                        Version 3, 29 June 2007
-
-     Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
-
-     Everyone is permitted to copy and distribute verbatim copies of this
-     license document, but changing it is not allowed.
-
-Preamble
-========
-
-The GNU General Public License is a free, copyleft license for software
-and other kinds of works.
-
-   The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program—to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-   When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-   To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-   For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-   Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-   For the developers’ and authors’ protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users’ and
-authors’ sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-   Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users’ freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-   Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-   The precise terms and conditions for copying, distribution and
-modification follow.
-
-TERMS AND CONDITIONS
-====================
-
-  0. Definitions.
-
-     “This License” refers to version 3 of the GNU General Public
-     License.
-
-     “Copyright” also means copyright-like laws that apply to other
-     kinds of works, such as semiconductor masks.
-
-     “The Program” refers to any copyrightable work licensed under this
-     License.  Each licensee is addressed as “you”.  “Licensees” and
-     “recipients” may be individuals or organizations.
-
-     To “modify” a work means to copy from or adapt all or part of the
-     work in a fashion requiring copyright permission, other than the
-     making of an exact copy.  The resulting work is called a “modified
-     version” of the earlier work or a work “based on” the earlier work.
-
-     A “covered work” means either the unmodified Program or a work
-     based on the Program.
-
-     To “propagate” a work means to do anything with it that, without
-     permission, would make you directly or secondarily liable for
-     infringement under applicable copyright law, except executing it on
-     a computer or modifying a private copy.  Propagation includes
-     copying, distribution (with or without modification), making
-     available to the public, and in some countries other activities as
-     well.
-
-     To “convey” a work means any kind of propagation that enables other
-     parties to make or receive copies.  Mere interaction with a user
-     through a computer network, with no transfer of a copy, is not
-     conveying.
-
-     An interactive user interface displays “Appropriate Legal Notices”
-     to the extent that it includes a convenient and prominently visible
-     feature that (1) displays an appropriate copyright notice, and (2)
-     tells the user that there is no warranty for the work (except to
-     the extent that warranties are provided), that licensees may convey
-     the work under this License, and how to view a copy of this
-     License.  If the interface presents a list of user commands or
-     options, such as a menu, a prominent item in the list meets this
-     criterion.
-
-  1. Source Code.
-
-     The “source code” for a work means the preferred form of the work
-     for making modifications to it.  “Object code” means any non-source
-     form of a work.
-
-     A “Standard Interface” means an interface that either is an
-     official standard defined by a recognized standards body, or, in
-     the case of interfaces specified for a particular programming
-     language, one that is widely used among developers working in that
-     language.
-
-     The “System Libraries” of an executable work include anything,
-     other than the work as a whole, that (a) is included in the normal
-     form of packaging a Major Component, but which is not part of that
-     Major Component, and (b) serves only to enable use of the work with
-     that Major Component, or to implement a Standard Interface for
-     which an implementation is available to the public in source code
-     form.  A “Major Component”, in this context, means a major
-     essential component (kernel, window system, and so on) of the
-     specific operating system (if any) on which the executable work
-     runs, or a compiler used to produce the work, or an object code
-     interpreter used to run it.
-
-     The “Corresponding Source” for a work in object code form means all
-     the source code needed to generate, install, and (for an executable
-     work) run the object code and to modify the work, including scripts
-     to control those activities.  However, it does not include the
-     work’s System Libraries, or general-purpose tools or generally
-     available free programs which are used unmodified in performing
-     those activities but which are not part of the work.  For example,
-     Corresponding Source includes interface definition files associated
-     with source files for the work, and the source code for shared
-     libraries and dynamically linked subprograms that the work is
-     specifically designed to require, such as by intimate data
-     communication or control flow between those subprograms and other
-     parts of the work.
-
-     The Corresponding Source need not include anything that users can
-     regenerate automatically from other parts of the Corresponding
-     Source.
-
-     The Corresponding Source for a work in source code form is that
-     same work.
-
-  2. Basic Permissions.
-
-     All rights granted under this License are granted for the term of
-     copyright on the Program, and are irrevocable provided the stated
-     conditions are met.  This License explicitly affirms your unlimited
-     permission to run the unmodified Program.  The output from running
-     a covered work is covered by this License only if the output, given
-     its content, constitutes a covered work.  This License acknowledges
-     your rights of fair use or other equivalent, as provided by
-     copyright law.
-
-     You may make, run and propagate covered works that you do not
-     convey, without conditions so long as your license otherwise
-     remains in force.  You may convey covered works to others for the
-     sole purpose of having them make modifications exclusively for you,
-     or provide you with facilities for running those works, provided
-     that you comply with the terms of this License in conveying all
-     material for which you do not control copyright.  Those thus making
-     or running the covered works for you must do so exclusively on your
-     behalf, under your direction and control, on terms that prohibit
-     them from making any copies of your copyrighted material outside
-     their relationship with you.
-
-     Conveying under any other circumstances is permitted solely under
-     the conditions stated below.  Sublicensing is not allowed; section
-     10 makes it unnecessary.
-
-  3. Protecting Users’ Legal Rights From Anti-Circumvention Law.
-
-     No covered work shall be deemed part of an effective technological
-     measure under any applicable law fulfilling obligations under
-     article 11 of the WIPO copyright treaty adopted on 20 December
-     1996, or similar laws prohibiting or restricting circumvention of
-     such measures.
-
-     When you convey a covered work, you waive any legal power to forbid
-     circumvention of technological measures to the extent such
-     circumvention is effected by exercising rights under this License
-     with respect to the covered work, and you disclaim any intention to
-     limit operation or modification of the work as a means of
-     enforcing, against the work’s users, your or third parties’ legal
-     rights to forbid circumvention of technological measures.
-
-  4. Conveying Verbatim Copies.
-
-     You may convey verbatim copies of the Program’s source code as you
-     receive it, in any medium, provided that you conspicuously and
-     appropriately publish on each copy an appropriate copyright notice;
-     keep intact all notices stating that this License and any
-     non-permissive terms added in accord with section 7 apply to the
-     code; keep intact all notices of the absence of any warranty; and
-     give all recipients a copy of this License along with the Program.
-
-     You may charge any price or no price for each copy that you convey,
-     and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-     You may convey a work based on the Program, or the modifications to
-     produce it from the Program, in the form of source code under the
-     terms of section 4, provided that you also meet all of these
-     conditions:
-
-       a. The work must carry prominent notices stating that you
-          modified it, and giving a relevant date.
-
-       b. The work must carry prominent notices stating that it is
-          released under this License and any conditions added under
-          section 7.  This requirement modifies the requirement in
-          section 4 to “keep intact all notices”.
-
-       c. You must license the entire work, as a whole, under this
-          License to anyone who comes into possession of a copy.  This
-          License will therefore apply, along with any applicable
-          section 7 additional terms, to the whole of the work, and all
-          its parts, regardless of how they are packaged.  This License
-          gives no permission to license the work in any other way, but
-          it does not invalidate such permission if you have separately
-          received it.
-
-       d. If the work has interactive user interfaces, each must display
-          Appropriate Legal Notices; however, if the Program has
-          interactive interfaces that do not display Appropriate Legal
-          Notices, your work need not make them do so.
-
-     A compilation of a covered work with other separate and independent
-     works, which are not by their nature extensions of the covered
-     work, and which are not combined with it such as to form a larger
-     program, in or on a volume of a storage or distribution medium, is
-     called an “aggregate” if the compilation and its resulting
-     copyright are not used to limit the access or legal rights of the
-     compilation’s users beyond what the individual works permit.
-     Inclusion of a covered work in an aggregate does not cause this
-     License to apply to the other parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-     You may convey a covered work in object code form under the terms
-     of sections 4 and 5, provided that you also convey the
-     machine-readable Corresponding Source under the terms of this
-     License, in one of these ways:
-
-       a. Convey the object code in, or embodied in, a physical product
-          (including a physical distribution medium), accompanied by the
-          Corresponding Source fixed on a durable physical medium
-          customarily used for software interchange.
-
-       b. Convey the object code in, or embodied in, a physical product
-          (including a physical distribution medium), accompanied by a
-          written offer, valid for at least three years and valid for as
-          long as you offer spare parts or customer support for that
-          product model, to give anyone who possesses the object code
-          either (1) a copy of the Corresponding Source for all the
-          software in the product that is covered by this License, on a
-          durable physical medium customarily used for software
-          interchange, for a price no more than your reasonable cost of
-          physically performing this conveying of source, or (2) access
-          to copy the Corresponding Source from a network server at no
-          charge.
-
-       c. Convey individual copies of the object code with a copy of the
-          written offer to provide the Corresponding Source.  This
-          alternative is allowed only occasionally and noncommercially,
-          and only if you received the object code with such an offer,
-          in accord with subsection 6b.
-
-       d. Convey the object code by offering access from a designated
-          place (gratis or for a charge), and offer equivalent access to
-          the Corresponding Source in the same way through the same
-          place at no further charge.  You need not require recipients
-          to copy the Corresponding Source along with the object code.
-          If the place to copy the object code is a network server, the
-          Corresponding Source may be on a different server (operated by
-          you or a third party) that supports equivalent copying
-          facilities, provided you maintain clear directions next to the
-          object code saying where to find the Corresponding Source.
-          Regardless of what server hosts the Corresponding Source, you
-          remain obligated to ensure that it is available for as long as
-          needed to satisfy these requirements.
-
-       e. Convey the object code using peer-to-peer transmission,
-          provided you inform other peers where the object code and
-          Corresponding Source of the work are being offered to the
-          general public at no charge under subsection 6d.
-
-     A separable portion of the object code, whose source code is
-     excluded from the Corresponding Source as a System Library, need
-     not be included in conveying the object code work.
-
-     A “User Product” is either (1) a “consumer product”, which means
-     any tangible personal property which is normally used for personal,
-     family, or household purposes, or (2) anything designed or sold for
-     incorporation into a dwelling.  In determining whether a product is
-     a consumer product, doubtful cases shall be resolved in favor of
-     coverage.  For a particular product received by a particular user,
-     “normally used” refers to a typical or common use of that class of
-     product, regardless of the status of the particular user or of the
-     way in which the particular user actually uses, or expects or is
-     expected to use, the product.  A product is a consumer product
-     regardless of whether the product has substantial commercial,
-     industrial or non-consumer uses, unless such uses represent the
-     only significant mode of use of the product.
-
-     “Installation Information” for a User Product means any methods,
-     procedures, authorization keys, or other information required to
-     install and execute modified versions of a covered work in that
-     User Product from a modified version of its Corresponding Source.
-     The information must suffice to ensure that the continued
-     functioning of the modified object code is in no case prevented or
-     interfered with solely because modification has been made.
-
-     If you convey an object code work under this section in, or with,
-     or specifically for use in, a User Product, and the conveying
-     occurs as part of a transaction in which the right of possession
-     and use of the User Product is transferred to the recipient in
-     perpetuity or for a fixed term (regardless of how the transaction
-     is characterized), the Corresponding Source conveyed under this
-     section must be accompanied by the Installation Information.  But
-     this requirement does not apply if neither you nor any third party
-     retains the ability to install modified object code on the User
-     Product (for example, the work has been installed in ROM).
-
-     The requirement to provide Installation Information does not
-     include a requirement to continue to provide support service,
-     warranty, or updates for a work that has been modified or installed
-     by the recipient, or for the User Product in which it has been
-     modified or installed.  Access to a network may be denied when the
-     modification itself materially and adversely affects the operation
-     of the network or violates the rules and protocols for
-     communication across the network.
-
-     Corresponding Source conveyed, and Installation Information
-     provided, in accord with this section must be in a format that is
-     publicly documented (and with an implementation available to the
-     public in source code form), and must require no special password
-     or key for unpacking, reading or copying.
-
-  7. Additional Terms.
-
-     “Additional permissions” are terms that supplement the terms of
-     this License by making exceptions from one or more of its
-     conditions.  Additional permissions that are applicable to the
-     entire Program shall be treated as though they were included in
-     this License, to the extent that they are valid under applicable
-     law.  If additional permissions apply only to part of the Program,
-     that part may be used separately under those permissions, but the
-     entire Program remains governed by this License without regard to
-     the additional permissions.
-
-     When you convey a copy of a covered work, you may at your option
-     remove any additional permissions from that copy, or from any part
-     of it.  (Additional permissions may be written to require their own
-     removal in certain cases when you modify the work.)  You may place
-     additional permissions on material, added by you to a covered work,
-     for which you have or can give appropriate copyright permission.
-
-     Notwithstanding any other provision of this License, for material
-     you add to a covered work, you may (if authorized by the copyright
-     holders of that material) supplement the terms of this License with
-     terms:
-
-       a. Disclaiming warranty or limiting liability differently from
-          the terms of sections 15 and 16 of this License; or
-
-       b. Requiring preservation of specified reasonable legal notices
-          or author attributions in that material or in the Appropriate
-          Legal Notices displayed by works containing it; or
-
-       c. Prohibiting misrepresentation of the origin of that material,
-          or requiring that modified versions of such material be marked
-          in reasonable ways as different from the original version; or
-
-       d. Limiting the use for publicity purposes of names of licensors
-          or authors of the material; or
-
-       e. Declining to grant rights under trademark law for use of some
-          trade names, trademarks, or service marks; or
-
-       f. Requiring indemnification of licensors and authors of that
-          material by anyone who conveys the material (or modified
-          versions of it) with contractual assumptions of liability to
-          the recipient, for any liability that these contractual
-          assumptions directly impose on those licensors and authors.
-
-     All other non-permissive additional terms are considered “further
-     restrictions” within the meaning of section 10.  If the Program as
-     you received it, or any part of it, contains a notice stating that
-     it is governed by this License along with a term that is a further
-     restriction, you may remove that term.  If a license document
-     contains a further restriction but permits relicensing or conveying
-     under this License, you may add to a covered work material governed
-     by the terms of that license document, provided that the further
-     restriction does not survive such relicensing or conveying.
-
-     If you add terms to a covered work in accord with this section, you
-     must place, in the relevant source files, a statement of the
-     additional terms that apply to those files, or a notice indicating
-     where to find the applicable terms.
-
-     Additional terms, permissive or non-permissive, may be stated in
-     the form of a separately written license, or stated as exceptions;
-     the above requirements apply either way.
-
-  8. Termination.
-
-     You may not propagate or modify a covered work except as expressly
-     provided under this License.  Any attempt otherwise to propagate or
-     modify it is void, and will automatically terminate your rights
-     under this License (including any patent licenses granted under the
-     third paragraph of section 11).
-
-     However, if you cease all violation of this License, then your
-     license from a particular copyright holder is reinstated (a)
-     provisionally, unless and until the copyright holder explicitly and
-     finally terminates your license, and (b) permanently, if the
-     copyright holder fails to notify you of the violation by some
-     reasonable means prior to 60 days after the cessation.
-
-     Moreover, your license from a particular copyright holder is
-     reinstated permanently if the copyright holder notifies you of the
-     violation by some reasonable means, this is the first time you have
-     received notice of violation of this License (for any work) from
-     that copyright holder, and you cure the violation prior to 30 days
-     after your receipt of the notice.
-
-     Termination of your rights under this section does not terminate
-     the licenses of parties who have received copies or rights from you
-     under this License.  If your rights have been terminated and not
-     permanently reinstated, you do not qualify to receive new licenses
-     for the same material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-     You are not required to accept this License in order to receive or
-     run a copy of the Program.  Ancillary propagation of a covered work
-     occurring solely as a consequence of using peer-to-peer
-     transmission to receive a copy likewise does not require
-     acceptance.  However, nothing other than this License grants you
-     permission to propagate or modify any covered work.  These actions
-     infringe copyright if you do not accept this License.  Therefore,
-     by modifying or propagating a covered work, you indicate your
-     acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-     Each time you convey a covered work, the recipient automatically
-     receives a license from the original licensors, to run, modify and
-     propagate that work, subject to this License.  You are not
-     responsible for enforcing compliance by third parties with this
-     License.
-
-     An “entity transaction” is a transaction transferring control of an
-     organization, or substantially all assets of one, or subdividing an
-     organization, or merging organizations.  If propagation of a
-     covered work results from an entity transaction, each party to that
-     transaction who receives a copy of the work also receives whatever
-     licenses to the work the party’s predecessor in interest had or
-     could give under the previous paragraph, plus a right to possession
-     of the Corresponding Source of the work from the predecessor in
-     interest, if the predecessor has it or can get it with reasonable
-     efforts.
-
-     You may not impose any further restrictions on the exercise of the
-     rights granted or affirmed under this License.  For example, you
-     may not impose a license fee, royalty, or other charge for exercise
-     of rights granted under this License, and you may not initiate
-     litigation (including a cross-claim or counterclaim in a lawsuit)
-     alleging that any patent claim is infringed by making, using,
-     selling, offering for sale, or importing the Program or any portion
-     of it.
-
-  11. Patents.
-
-     A “contributor” is a copyright holder who authorizes use under this
-     License of the Program or a work on which the Program is based.
-     The work thus licensed is called the contributor’s “contributor
-     version”.
-
-     A contributor’s “essential patent claims” are all patent claims
-     owned or controlled by the contributor, whether already acquired or
-     hereafter acquired, that would be infringed by some manner,
-     permitted by this License, of making, using, or selling its
-     contributor version, but do not include claims that would be
-     infringed only as a consequence of further modification of the
-     contributor version.  For purposes of this definition, “control”
-     includes the right to grant patent sublicenses in a manner
-     consistent with the requirements of this License.
-
-     Each contributor grants you a non-exclusive, worldwide,
-     royalty-free patent license under the contributor’s essential
-     patent claims, to make, use, sell, offer for sale, import and
-     otherwise run, modify and propagate the contents of its contributor
-     version.
-
-     In the following three paragraphs, a “patent license” is any
-     express agreement or commitment, however denominated, not to
-     enforce a patent (such as an express permission to practice a
-     patent or covenant not to sue for patent infringement).  To “grant”
-     such a patent license to a party means to make such an agreement or
-     commitment not to enforce a patent against the party.
-
-     If you convey a covered work, knowingly relying on a patent
-     license, and the Corresponding Source of the work is not available
-     for anyone to copy, free of charge and under the terms of this
-     License, through a publicly available network server or other
-     readily accessible means, then you must either (1) cause the
-     Corresponding Source to be so available, or (2) arrange to deprive
-     yourself of the benefit of the patent license for this particular
-     work, or (3) arrange, in a manner consistent with the requirements
-     of this License, to extend the patent license to downstream
-     recipients.  “Knowingly relying” means you have actual knowledge
-     that, but for the patent license, your conveying the covered work
-     in a country, or your recipient’s use of the covered work in a
-     country, would infringe one or more identifiable patents in that
-     country that you have reason to believe are valid.
-
-     If, pursuant to or in connection with a single transaction or
-     arrangement, you convey, or propagate by procuring conveyance of, a
-     covered work, and grant a patent license to some of the parties
-     receiving the covered work authorizing them to use, propagate,
-     modify or convey a specific copy of the covered work, then the
-     patent license you grant is automatically extended to all
-     recipients of the covered work and works based on it.
-
-     A patent license is “discriminatory” if it does not include within
-     the scope of its coverage, prohibits the exercise of, or is
-     conditioned on the non-exercise of one or more of the rights that
-     are specifically granted under this License.  You may not convey a
-     covered work if you are a party to an arrangement with a third
-     party that is in the business of distributing software, under which
-     you make payment to the third party based on the extent of your
-     activity of conveying the work, and under which the third party
-     grants, to any of the parties who would receive the covered work
-     from you, a discriminatory patent license (a) in connection with
-     copies of the covered work conveyed by you (or copies made from
-     those copies), or (b) primarily for and in connection with specific
-     products or compilations that contain the covered work, unless you
-     entered into that arrangement, or that patent license was granted,
-     prior to 28 March 2007.
-
-     Nothing in this License shall be construed as excluding or limiting
-     any implied license or other defenses to infringement that may
-     otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others’ Freedom.
-
-     If conditions are imposed on you (whether by court order, agreement
-     or otherwise) that contradict the conditions of this License, they
-     do not excuse you from the conditions of this License.  If you
-     cannot convey a covered work so as to satisfy simultaneously your
-     obligations under this License and any other pertinent obligations,
-     then as a consequence you may not convey it at all.  For example,
-     if you agree to terms that obligate you to collect a royalty for
-     further conveying from those to whom you convey the Program, the
-     only way you could satisfy both those terms and this License would
-     be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-     Notwithstanding any other provision of this License, you have
-     permission to link or combine any covered work with a work licensed
-     under version 3 of the GNU Affero General Public License into a
-     single combined work, and to convey the resulting work.  The terms
-     of this License will continue to apply to the part which is the
-     covered work, but the special requirements of the GNU Affero
-     General Public License, section 13, concerning interaction through
-     a network will apply to the combination as such.
-
-  14. Revised Versions of this License.
-
-     The Free Software Foundation may publish revised and/or new
-     versions of the GNU General Public License from time to time.  Such
-     new versions will be similar in spirit to the present version, but
-     may differ in detail to address new problems or concerns.
-
-     Each version is given a distinguishing version number.  If the
-     Program specifies that a certain numbered version of the GNU
-     General Public License “or any later version” applies to it, you
-     have the option of following the terms and conditions either of
-     that numbered version or of any later version published by the Free
-     Software Foundation.  If the Program does not specify a version
-     number of the GNU General Public License, you may choose any
-     version ever published by the Free Software Foundation.
-
-     If the Program specifies that a proxy can decide which future
-     versions of the GNU General Public License can be used, that
-     proxy’s public statement of acceptance of a version permanently
-     authorizes you to choose that version for the Program.
-
-     Later license versions may give you additional or different
-     permissions.  However, no additional obligations are imposed on any
-     author or copyright holder as a result of your choosing to follow a
-     later version.
-
-  15. Disclaimer of Warranty.
-
-     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-     APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE
-     COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS”
-     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
-     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE
-     RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
-     SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
-     NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES
-     AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
-     DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-     CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
-     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
-     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-     PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
-     THE POSSIBILITY OF SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-     If the disclaimer of warranty and limitation of liability provided
-     above cannot be given local legal effect according to their terms,
-     reviewing courts shall apply local law that most closely
-     approximates an absolute waiver of all civil liability in
-     connection with the Program, unless a warranty or assumption of
-     liability accompanies a copy of the Program in return for a fee.
-
-END OF TERMS AND CONDITIONS
-===========================
-
-How to Apply These Terms to Your New Programs
-=============================================
-
-If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
-
-   To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least the
-“copyright” line and a pointer to where the full notice is found.
-
-     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
-     Copyright (C) YEAR NAME OF AUTHOR
-
-     This program is free software: you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation, either version 3 of the License, or (at
-     your option) any later version.
-
-     This program is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-   Also add information on how to contact you by electronic and paper
-mail.
-
-   If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-     PROGRAM Copyright (C) YEAR NAME OF AUTHOR
-     This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
-     This is free software, and you are welcome to redistribute it
-     under certain conditions; type ‘show c’ for details.
-
-   The hypothetical commands ‘show w’ and ‘show c’ should show the
-appropriate parts of the General Public License.  Of course, your
-program’s commands might be different; for a GUI interface, you would
-use an “about box”.
-
-   You should also get your employer (if you work as a programmer) or
-school, if any, to sign a “copyright disclaimer” for the program, if
-necessary.  For more information on this, and how to apply and follow
-the GNU GPL, see <https://www.gnu.org/licenses/>.
-
-   The GNU General Public License does not permit incorporating your
-program into proprietary programs.  If your program is a subroutine
-library, you may consider it more useful to permit linking proprietary
-applications with the library.  If this is what you want to do, use the
-GNU Lesser General Public License instead of this License.  But first,
-please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
-
-\1f
-File: dash.info,  Node: Index,  Prev: GPL,  Up: Top
-
-Index
-*****
-
-\0\b[index\0\b]
-* Menu:
-
-* !cdr:                                  Destructive operations.
-                                                              (line  16)
-* !cons:                                 Destructive operations.
-                                                              (line   8)
-* -->:                                   Threading macros.    (line  35)
-* ->:                                    Threading macros.    (line   9)
-* ->>:                                   Threading macros.    (line  22)
-* -all?:                                 Predicates.          (line  53)
-* -andfn:                                Function combinators.
-                                                              (line 184)
-* -annotate:                             Maps.                (line  86)
-* -any?:                                 Predicates.          (line  41)
-* -applify:                              Function combinators.
-                                                              (line  63)
-* -as->:                                 Threading macros.    (line  49)
-* -butlast:                              Other list operations.
-                                                              (line 405)
-* -clone:                                Tree operations.     (line 123)
-* -common-prefix:                        Reductions.          (line 242)
-* -common-suffix:                        Reductions.          (line 252)
-* -compose:                              Function combinators.
-                                                              (line  49)
-* -concat:                               List to list.        (line  23)
-* -cons*:                                Other list operations.
-                                                              (line  19)
-* -cons-pair?:                           Predicates.          (line 154)
-* -const:                                Function combinators.
-                                                              (line 128)
-* -contains?:                            Predicates.          (line 100)
-* -copy:                                 Maps.                (line 151)
-* -count:                                Reductions.          (line 172)
-* -cut:                                  Function combinators.
-                                                              (line 140)
-* -cycle:                                Unfolding.           (line  55)
-* -difference:                           Set operations.      (line  22)
-* -distinct:                             Set operations.      (line  73)
-* -dotimes:                              Side effects.        (line  80)
-* -doto:                                 Threading macros.    (line  99)
-* -drop:                                 Sublist selection.   (line 149)
-* -drop-last:                            Sublist selection.   (line 163)
-* -drop-while:                           Sublist selection.   (line 194)
-* -each:                                 Side effects.        (line   8)
-* -each-indexed:                         Side effects.        (line  38)
-* -each-r:                               Side effects.        (line  52)
-* -each-r-while:                         Side effects.        (line  65)
-* -each-while:                           Side effects.        (line  24)
-* -elem-index:                           Indexing.            (line   9)
-* -elem-indices:                         Indexing.            (line  23)
-* -every:                                Predicates.          (line  23)
-* -fifth-item:                           Other list operations.
-                                                              (line 380)
-* -filter:                               Sublist selection.   (line   8)
-* -find-index:                           Indexing.            (line  35)
-* -find-indices:                         Indexing.            (line  73)
-* -find-last-index:                      Indexing.            (line  54)
-* -first:                                Other list operations.
-                                                              (line 300)
-* -first-item:                           Other list operations.
-                                                              (line 328)
-* -fix:                                  Other list operations.
-                                                              (line 445)
-* -fixfn:                                Function combinators.
-                                                              (line 224)
-* -flatten:                              List to list.        (line  38)
-* -flatten-n:                            List to list.        (line  60)
-* -flip:                                 Function combinators.
-                                                              (line  95)
-* -fourth-item:                          Other list operations.
-                                                              (line 367)
-* -frequencies:                          Reductions.          (line 310)
-* -grade-down:                           Indexing.            (line 103)
-* -grade-up:                             Indexing.            (line  93)
-* -group-by:                             Partitioning.        (line 205)
-* -if-let:                               Binding.             (line  34)
-* -if-let*:                              Binding.             (line  45)
-* -inits:                                Reductions.          (line 222)
-* -insert-at:                            List to list.        (line 114)
-* -interleave:                           Other list operations.
-                                                              (line  56)
-* -interpose:                            Other list operations.
-                                                              (line  46)
-* -intersection:                         Set operations.      (line  36)
-* -iota:                                 Other list operations.
-                                                              (line  67)
-* -is-infix?:                            Predicates.          (line 140)
-* -is-prefix?:                           Predicates.          (line 116)
-* -is-suffix?:                           Predicates.          (line 128)
-* -iterate:                              Unfolding.           (line   9)
-* -iteratefn:                            Function combinators.
-                                                              (line 201)
-* -juxt:                                 Function combinators.
-                                                              (line  37)
-* -keep:                                 List to list.        (line   8)
-* -lambda:                               Binding.             (line 247)
-* -last:                                 Other list operations.
-                                                              (line 318)
-* -last-item:                            Other list operations.
-                                                              (line 393)
-* -let:                                  Binding.             (line  61)
-* -let*:                                 Binding.             (line 227)
-* -list:                                 Other list operations.
-                                                              (line 428)
-* -map:                                  Maps.                (line  10)
-* -map-first:                            Maps.                (line  38)
-* -map-indexed:                          Maps.                (line  68)
-* -map-last:                             Maps.                (line  53)
-* -map-when:                             Maps.                (line  22)
-* -mapcat:                               Maps.                (line 140)
-* -max:                                  Reductions.          (line 286)
-* -max-by:                               Reductions.          (line 296)
-* -min:                                  Reductions.          (line 262)
-* -min-by:                               Reductions.          (line 272)
-* -non-nil:                              Sublist selection.   (line  95)
-* -none?:                                Predicates.          (line  73)
-* -not:                                  Function combinators.
-                                                              (line 153)
-* -on:                                   Function combinators.
-                                                              (line  75)
-* -only-some?:                           Predicates.          (line  85)
-* -orfn:                                 Function combinators.
-                                                              (line 167)
-* -pad:                                  Other list operations.
-                                                              (line 241)
-* -partial:                              Function combinators.
-                                                              (line   8)
-* -partition:                            Partitioning.        (line  90)
-* -partition-after-item:                 Partitioning.        (line 195)
-* -partition-after-pred:                 Partitioning.        (line 162)
-* -partition-all:                        Partitioning.        (line 102)
-* -partition-all-in-steps:               Partitioning.        (line 126)
-* -partition-before-item:                Partitioning.        (line 185)
-* -partition-before-pred:                Partitioning.        (line 174)
-* -partition-by:                         Partitioning.        (line 138)
-* -partition-by-header:                  Partitioning.        (line 149)
-* -partition-in-steps:                   Partitioning.        (line 113)
-* -permutations:                         Set operations.      (line  60)
-* -powerset:                             Set operations.      (line  50)
-* -prodfn:                               Function combinators.
-                                                              (line 258)
-* -product:                              Reductions.          (line 201)
-* -reduce:                               Reductions.          (line  53)
-* -reduce-from:                          Reductions.          (line   8)
-* -reduce-r:                             Reductions.          (line  72)
-* -reduce-r-from:                        Reductions.          (line  26)
-* -reductions:                           Reductions.          (line 136)
-* -reductions-from:                      Reductions.          (line 100)
-* -reductions-r:                         Reductions.          (line 154)
-* -reductions-r-from:                    Reductions.          (line 118)
-* -remove:                               Sublist selection.   (line  26)
-* -remove-at:                            List to list.        (line 151)
-* -remove-at-indices:                    List to list.        (line 170)
-* -remove-first:                         Sublist selection.   (line  44)
-* -remove-item:                          Sublist selection.   (line  84)
-* -remove-last:                          Sublist selection.   (line  65)
-* -repeat:                               Unfolding.           (line  44)
-* -replace:                              List to list.        (line  72)
-* -replace-at:                           List to list.        (line 125)
-* -replace-first:                        List to list.        (line  86)
-* -replace-last:                         List to list.        (line 100)
-* -rotate:                               Other list operations.
-                                                              (line   8)
-* -rotate-args:                          Function combinators.
-                                                              (line 112)
-* -rpartial:                             Function combinators.
-                                                              (line  22)
-* -running-product:                      Reductions.          (line 211)
-* -running-sum:                          Reductions.          (line 190)
-* -same-items?:                          Set operations.      (line  88)
-* -second-item:                          Other list operations.
-                                                              (line 341)
-* -select-by-indices:                    Sublist selection.   (line 211)
-* -select-column:                        Sublist selection.   (line 241)
-* -select-columns:                       Sublist selection.   (line 222)
-* -separate:                             Partitioning.        (line  75)
-* -setq:                                 Binding.             (line 270)
-* -slice:                                Sublist selection.   (line 105)
-* -snoc:                                 Other list operations.
-                                                              (line  32)
-* -some:                                 Predicates.          (line   8)
-* -some-->:                              Threading macros.    (line  86)
-* -some->:                               Threading macros.    (line  62)
-* -some->>:                              Threading macros.    (line  74)
-* -sort:                                 Other list operations.
-                                                              (line 415)
-* -splice:                               Maps.                (line 102)
-* -splice-list:                          Maps.                (line 127)
-* -split-at:                             Partitioning.        (line   8)
-* -split-on:                             Partitioning.        (line  40)
-* -split-when:                           Partitioning.        (line  58)
-* -split-with:                           Partitioning.        (line  23)
-* -sum:                                  Reductions.          (line 180)
-* -table:                                Other list operations.
-                                                              (line 256)
-* -table-flat:                           Other list operations.
-                                                              (line 275)
-* -tails:                                Reductions.          (line 232)
-* -take:                                 Sublist selection.   (line 121)
-* -take-last:                            Sublist selection.   (line 135)
-* -take-while:                           Sublist selection.   (line 177)
-* -third-item:                           Other list operations.
-                                                              (line 354)
-* -tree-map:                             Tree operations.     (line  28)
-* -tree-map-nodes:                       Tree operations.     (line  39)
-* -tree-mapreduce:                       Tree operations.     (line  85)
-* -tree-mapreduce-from:                  Tree operations.     (line 104)
-* -tree-reduce:                          Tree operations.     (line  53)
-* -tree-reduce-from:                     Tree operations.     (line  70)
-* -tree-seq:                             Tree operations.     (line   8)
-* -unfold:                               Unfolding.           (line  25)
-* -union:                                Set operations.      (line   8)
-* -unzip:                                Other list operations.
-                                                              (line 215)
-* -unzip-lists:                          Other list operations.
-                                                              (line 196)
-* -update-at:                            List to list.        (line 137)
-* -when-let:                             Binding.             (line   9)
-* -when-let*:                            Binding.             (line  21)
-* -zip:                                  Other list operations.
-                                                              (line 150)
-* -zip-fill:                             Other list operations.
-                                                              (line 176)
-* -zip-lists:                            Other list operations.
-                                                              (line 114)
-* -zip-lists-fill:                       Other list operations.
-                                                              (line 135)
-* -zip-pair:                             Other list operations.
-                                                              (line  98)
-* -zip-with:                             Other list operations.
-                                                              (line  80)
-* dash-fontify-mode:                     Fontification of special variables.
-                                                              (line   6)
-* dash-register-info-lookup:             Info symbol lookup.  (line   6)
-* global-dash-fontify-mode:              Fontification of special variables.
-                                                              (line  12)
-
-
-\1f
-Tag Table:
-Node: Top\7f742
-Node: Installation\7f2397
-Node: Using in a package\7f3159
-Node: Fontification of special variables\7f3504
-Node: Info symbol lookup\7f4294
-Node: Functions\7f4877
-Node: Maps\7f6361
-Ref: -map\7f6658
-Ref: -map-when\7f7031
-Ref: -map-first\7f7605
-Ref: -map-last\7f8200
-Ref: -map-indexed\7f8790
-Ref: -annotate\7f9476
-Ref: -splice\7f10080
-Ref: -splice-list\7f11155
-Ref: -mapcat\7f11614
-Ref: -copy\7f11987
-Node: Sublist selection\7f12175
-Ref: -filter\7f12368
-Ref: -remove\7f12921
-Ref: -remove-first\7f13470
-Ref: -remove-last\7f14318
-Ref: -remove-item\7f15048
-Ref: -non-nil\7f15448
-Ref: -slice\7f15730
-Ref: -take\7f16259
-Ref: -take-last\7f16677
-Ref: -drop\7f17114
-Ref: -drop-last\7f17561
-Ref: -take-while\7f17993
-Ref: -drop-while\7f18620
-Ref: -select-by-indices\7f19253
-Ref: -select-columns\7f19764
-Ref: -select-column\7f20467
-Node: List to list\7f20930
-Ref: -keep\7f21122
-Ref: -concat\7f21698
-Ref: -flatten\7f22226
-Ref: -flatten-n\7f22988
-Ref: -replace\7f23372
-Ref: -replace-first\7f23833
-Ref: -replace-last\7f24328
-Ref: -insert-at\7f24816
-Ref: -replace-at\7f25141
-Ref: -update-at\7f25528
-Ref: -remove-at\7f26069
-Ref: -remove-at-indices\7f26696
-Node: Reductions\7f27386
-Ref: -reduce-from\7f27582
-Ref: -reduce-r-from\7f28306
-Ref: -reduce\7f29569
-Ref: -reduce-r\7f30320
-Ref: -reductions-from\7f31598
-Ref: -reductions-r-from\7f32404
-Ref: -reductions\7f33234
-Ref: -reductions-r\7f33945
-Ref: -count\7f34690
-Ref: -sum\7f34920
-Ref: -running-sum\7f35108
-Ref: -product\7f35429
-Ref: -running-product\7f35637
-Ref: -inits\7f35978
-Ref: -tails\7f36223
-Ref: -common-prefix\7f36468
-Ref: -common-suffix\7f36762
-Ref: -min\7f37056
-Ref: -min-by\7f37282
-Ref: -max\7f37803
-Ref: -max-by\7f38028
-Ref: -frequencies\7f38554
-Node: Unfolding\7f39169
-Ref: -iterate\7f39410
-Ref: -unfold\7f39857
-Ref: -repeat\7f40662
-Ref: -cycle\7f40946
-Node: Predicates\7f41343
-Ref: -some\7f41520
-Ref: -every\7f41949
-Ref: -any?\7f42663
-Ref: -all?\7f43012
-Ref: -none?\7f43754
-Ref: -only-some?\7f44074
-Ref: -contains?\7f44619
-Ref: -is-prefix?\7f45125
-Ref: -is-suffix?\7f45457
-Ref: -is-infix?\7f45789
-Ref: -cons-pair?\7f46149
-Node: Partitioning\7f46480
-Ref: -split-at\7f46668
-Ref: -split-with\7f47332
-Ref: -split-on\7f47972
-Ref: -split-when\7f48643
-Ref: -separate\7f49286
-Ref: -partition\7f49820
-Ref: -partition-all\7f50269
-Ref: -partition-in-steps\7f50694
-Ref: -partition-all-in-steps\7f51240
-Ref: -partition-by\7f51754
-Ref: -partition-by-header\7f52132
-Ref: -partition-after-pred\7f52733
-Ref: -partition-before-pred\7f53186
-Ref: -partition-before-item\7f53571
-Ref: -partition-after-item\7f53878
-Ref: -group-by\7f54180
-Node: Indexing\7f54613
-Ref: -elem-index\7f54815
-Ref: -elem-indices\7f55302
-Ref: -find-index\7f55761
-Ref: -find-last-index\7f56430
-Ref: -find-indices\7f57081
-Ref: -grade-up\7f57843
-Ref: -grade-down\7f58250
-Node: Set operations\7f58664
-Ref: -union\7f58847
-Ref: -difference\7f59277
-Ref: -intersection\7f59705
-Ref: -powerset\7f60134
-Ref: -permutations\7f60411
-Ref: -distinct\7f60849
-Ref: -same-items?\7f61243
-Node: Other list operations\7f61852
-Ref: -rotate\7f62077
-Ref: -cons*\7f62430
-Ref: -snoc\7f62852
-Ref: -interpose\7f63264
-Ref: -interleave\7f63558
-Ref: -iota\7f63924
-Ref: -zip-with\7f64407
-Ref: -zip-pair\7f65215
-Ref: -zip-lists\7f65781
-Ref: -zip-lists-fill\7f66579
-Ref: -zip\7f67289
-Ref: -zip-fill\7f68316
-Ref: -unzip-lists\7f69230
-Ref: -unzip\7f69853
-Ref: -pad\7f70846
-Ref: -table\7f71331
-Ref: -table-flat\7f72117
-Ref: -first\7f73122
-Ref: -last\7f73655
-Ref: -first-item\7f74001
-Ref: -second-item\7f74413
-Ref: -third-item\7f74830
-Ref: -fourth-item\7f75205
-Ref: -fifth-item\7f75583
-Ref: -last-item\7f75958
-Ref: -butlast\7f76319
-Ref: -sort\7f76564
-Ref: -list\7f77058
-Ref: -fix\7f77627
-Node: Tree operations\7f78116
-Ref: -tree-seq\7f78312
-Ref: -tree-map\7f79173
-Ref: -tree-map-nodes\7f79613
-Ref: -tree-reduce\7f80477
-Ref: -tree-reduce-from\7f81359
-Ref: -tree-mapreduce\7f81959
-Ref: -tree-mapreduce-from\7f82818
-Ref: -clone\7f84103
-Node: Threading macros\7f84441
-Ref: ->\7f84666
-Ref: ->>\7f85154
-Ref: -->\7f85657
-Ref: -as->\7f86214
-Ref: -some->\7f86668
-Ref: -some->>\7f87053
-Ref: -some-->\7f87500
-Ref: -doto\7f88067
-Node: Binding\7f88620
-Ref: -when-let\7f88827
-Ref: -when-let*\7f89288
-Ref: -if-let\7f89817
-Ref: -if-let*\7f90183
-Ref: -let\7f90806
-Ref: -let*\7f96896
-Ref: -lambda\7f97833
-Ref: -setq\7f98639
-Node: Side effects\7f99440
-Ref: -each\7f99634
-Ref: -each-while\7f100161
-Ref: -each-indexed\7f100781
-Ref: -each-r\7f101373
-Ref: -each-r-while\7f101815
-Ref: -dotimes\7f102459
-Node: Destructive operations\7f103012
-Ref: !cons\7f103230
-Ref: !cdr\7f103434
-Node: Function combinators\7f103627
-Ref: -partial\7f103831
-Ref: -rpartial\7f104349
-Ref: -juxt\7f104997
-Ref: -compose\7f105449
-Ref: -applify\7f106056
-Ref: -on\7f106486
-Ref: -flip\7f107258
-Ref: -rotate-args\7f107782
-Ref: -const\7f108411
-Ref: -cut\7f108753
-Ref: -not\7f109233
-Ref: -orfn\7f109777
-Ref: -andfn\7f110570
-Ref: -iteratefn\7f111357
-Ref: -fixfn\7f112059
-Ref: -prodfn\7f113633
-Node: Development\7f114784
-Node: Contribute\7f115073
-Node: Contributors\7f116085
-Node: FDL\7f118178
-Node: GPL\7f143498
-Node: Index\7f181247
-\1f
-End Tag Table
-
-\1f
-Local Variables:
-coding: utf-8
-End:
diff --git a/elpa/dash-20240510.1327/dir b/elpa/dash-20240510.1327/dir
deleted file mode 100644 (file)
index 7d473f4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-This is the file .../info/dir, which contains the
-topmost node of the Info hierarchy, called (dir)Top.
-The first time you invoke Info you start off looking at this node.
-\1f
-File: dir,     Node: Top       This is the top of the INFO tree
-
-  This (the Directory node) gives a menu of major topics.
-  Typing "q" exits, "H" lists all Info commands, "d" returns here,
-  "h" gives a primer for first-timers,
-  "mEmacs<Return>" visits the Emacs manual, etc.
-
-  In Emacs, you can click mouse button 2 on a menu item or cross reference
-  to select it.
-
-* Menu:
-
-Emacs
-* Dash: (dash.info).            A modern list library for GNU Emacs.
diff --git a/elpa/dash-20250312.1307/dash-autoloads.el b/elpa/dash-20250312.1307/dash-autoloads.el
new file mode 100644 (file)
index 0000000..3d8c46f
--- /dev/null
@@ -0,0 +1,83 @@
+;;; dash-autoloads.el --- automatically extracted autoloads (do not edit)   -*- lexical-binding: t -*-
+;; Generated by the `loaddefs-generate' function.
+
+;; This file is part of GNU Emacs.
+
+;;; Code:
+
+(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
+
+
+\f
+;;; Generated autoloads from dash.el
+
+(autoload 'dash-fontify-mode "dash" "\
+Toggle fontification of Dash special variables.
+
+Dash-Fontify mode is a buffer-local minor mode intended for Emacs
+Lisp buffers.  Enabling it causes the special variables bound in
+anaphoric Dash macros to be fontified.  These anaphoras include
+`it', `it-index', `acc', and `other'.  In older Emacs versions
+which do not dynamically detect macros, Dash-Fontify mode
+additionally fontifies Dash macro calls.
+
+See also `dash-fontify-mode-lighter' and
+`global-dash-fontify-mode'.
+
+This is a minor mode.  If called interactively, toggle the `Dash-Fontify
+mode' mode.  If the prefix argument is positive, enable the mode, and if
+it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable the
+mode if ARG is nil, omitted, or is a positive number.  Disable the mode
+if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate the variable `dash-fontify-mode'.
+
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
+
+(fn &optional ARG)" t)
+(put 'global-dash-fontify-mode 'globalized-minor-mode t)
+(defvar global-dash-fontify-mode nil "\
+Non-nil if Global Dash-Fontify mode is enabled.
+See the `global-dash-fontify-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `global-dash-fontify-mode'.")
+(custom-autoload 'global-dash-fontify-mode "dash" nil)
+(autoload 'global-dash-fontify-mode "dash" "\
+Toggle Dash-Fontify mode in all buffers.
+With prefix ARG, enable Global Dash-Fontify mode if ARG is positive;
+otherwise, disable it.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.
+Enable the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+Dash-Fontify mode is enabled in all buffers where
+`dash--turn-on-fontify-mode' would do it.
+
+See `dash-fontify-mode' for more information on Dash-Fontify mode.
+
+(fn &optional ARG)" t)
+(autoload 'dash-register-info-lookup "dash" "\
+Register the Dash Info manual with `info-lookup-symbol'.
+This allows Dash symbols to be looked up with \\[info-lookup-symbol]." t)
+(register-definition-prefixes "dash" '("!cdr" "!cons" "--" "->" "-a" "-butlast" "-c" "-d" "-e" "-f" "-gr" "-i" "-juxt" "-keep" "-l" "-m" "-no" "-o" "-p" "-r" "-s" "-t" "-u" "-value-to-list" "-when-let" "-zip" "dash-"))
+\f
+;;; End of scraped data
+
+(provide 'dash-autoloads)
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; no-native-compile: t
+;; coding: utf-8-emacs-unix
+;; End:
+
+;;; dash-autoloads.el ends here
diff --git a/elpa/dash-20250312.1307/dash-pkg.el b/elpa/dash-20250312.1307/dash-pkg.el
new file mode 100644 (file)
index 0000000..3fd56b1
--- /dev/null
@@ -0,0 +1,10 @@
+;; -*- no-byte-compile: t; lexical-binding: nil -*-
+(define-package "dash" "20250312.1307"
+  "A modern list library for Emacs."
+  '((emacs "24"))
+  :url "https://github.com/magnars/dash.el"
+  :commit "fcb5d831fc08a43f984242c7509870f30983c27c"
+  :revdesc "fcb5d831fc08"
+  :keywords '("extensions" "lisp")
+  :authors '(("Magnar Sveen" . "magnarsNOSPAMgmail.com"))
+  :maintainers '(("Basil L. Contovounesios" . "basilNOSPAMcontovou.net")))
diff --git a/elpa/dash-20250312.1307/dash.el b/elpa/dash-20250312.1307/dash.el
new file mode 100644 (file)
index 0000000..b23ffcf
--- /dev/null
@@ -0,0 +1,4165 @@
+;;; dash.el --- A modern list library for Emacs  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012-2025 Free Software Foundation, Inc.
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.com>
+;; Maintainer: Basil L. Contovounesios <basilNOSPAMcontovou.net>
+;; Package-Version: 20250312.1307
+;; Package-Revision: fcb5d831fc08
+;; Package-Requires: ((emacs "24"))
+;; Keywords: extensions, lisp
+;; URL: https://github.com/magnars/dash.el
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A modern list API for Emacs.
+;;
+;; See its overview at https://github.com/magnars/dash.el#functions.
+
+;;; Code:
+
+(eval-when-compile
+  (unless (fboundp 'static-if)
+    (defmacro static-if (condition then-form &rest else-forms)
+      "Expand to THEN-FORM or ELSE-FORMS based on compile-time CONDITION.
+Polyfill for Emacs 30 `static-if'."
+      (declare (debug (sexp sexp &rest sexp)) (indent 2))
+      (if (eval condition lexical-binding)
+          then-form
+        (cons 'progn else-forms))))
+
+  ;; TODO: Emacs 24.3 first introduced `gv', so remove this and all
+  ;; calls to `defsetf' when support for earlier versions is dropped.
+  (unless (fboundp 'gv-define-setter)
+    (require 'cl))
+
+  ;; - 24.3 started complaining about unknown `declare' props.
+  ;; - 25 introduced `pure' and `side-effect-free'.
+  ;; - 30 introduced `important-return-value'.
+  (when (boundp 'defun-declarations-alist)
+    (dolist (prop '(important-return-value pure side-effect-free))
+      (unless (assq prop defun-declarations-alist)
+        (push (list prop #'ignore) defun-declarations-alist)))))
+
+(defgroup dash ()
+  "Customize group for Dash, a modern list library."
+  :group 'extensions
+  :group 'lisp
+  :prefix "dash-")
+
+(defmacro !cons (car cdr)
+  "Destructive: Set CDR to the cons of CAR and CDR."
+  (declare (debug (form symbolp)))
+  `(setq ,cdr (cons ,car ,cdr)))
+
+(defmacro !cdr (list)
+  "Destructive: Set LIST to the cdr of LIST."
+  (declare (debug (symbolp)))
+  `(setq ,list (cdr ,list)))
+
+(defmacro --each (list &rest body)
+  "Evaluate BODY for each element of LIST and return nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating BODY.
+This is the anaphoric counterpart to `-each'."
+  (declare (debug (form body)) (indent 1))
+  (let ((l (make-symbol "list"))
+        (i (make-symbol "i")))
+    `(let ((,l ,list)
+           (,i 0))
+       (while ,l
+         (let ((it (pop ,l)) (it-index ,i))
+           (ignore it it-index)
+           ,@body)
+         (setq ,i (1+ ,i))))))
+
+(defun -each (list fn)
+  "Call FN on each element of LIST.
+Return nil; this function is intended for side effects.
+
+Its anaphoric counterpart is `--each'.
+
+For access to the current element's index in LIST, see
+`-each-indexed'."
+  (declare (indent 1))
+  (ignore (mapc fn list)))
+
+(defalias '--each-indexed '--each)
+
+(defun -each-indexed (list fn)
+  "Call FN on each index and element of LIST.
+For each ITEM at INDEX in LIST, call (funcall FN INDEX ITEM).
+Return nil; this function is intended for side effects.
+
+See also: `-map-indexed'."
+  (declare (indent 1))
+  (--each list (funcall fn it-index it)))
+
+(defmacro --each-while (list pred &rest body)
+  "Evaluate BODY for each item in LIST, while PRED evaluates to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating PRED or BODY.  Once
+an element is reached for which PRED evaluates to nil, no further
+BODY is evaluated.  The return value is always nil.
+This is the anaphoric counterpart to `-each-while'."
+  (declare (debug (form form body)) (indent 2))
+  (let ((l (make-symbol "list"))
+        (i (make-symbol "i"))
+        (elt (make-symbol "elt")))
+    `(let ((,l ,list)
+           (,i 0)
+           ,elt)
+       (while (when ,l
+                (setq ,elt (car-safe ,l))
+                (let ((it ,elt) (it-index ,i))
+                  (ignore it it-index)
+                  ,pred))
+         (let ((it ,elt) (it-index ,i))
+           (ignore it it-index)
+           ,@body)
+         (setq ,i (1+ ,i) ,l (cdr ,l))))))
+
+(defun -each-while (list pred fn)
+  "Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil.
+Once an ITEM is reached for which PRED returns nil, FN is no
+longer called.  Return nil; this function is intended for side
+effects.
+
+Its anaphoric counterpart is `--each-while'."
+  (declare (indent 2))
+  (--each-while list (funcall pred it) (funcall fn it)))
+
+(defmacro --each-r (list &rest body)
+  "Evaluate BODY for each element of LIST in reversed order.
+Each element of LIST in turn, starting at its end, is bound to
+`it' and its index within LIST to `it-index' before evaluating
+BODY.  The return value is always nil.
+This is the anaphoric counterpart to `-each-r'."
+  (declare (debug (form body)) (indent 1))
+  (let ((v (make-symbol "vector"))
+        (i (make-symbol "i")))
+    ;; Implementation note: building a vector is considerably faster
+    ;; than building a reversed list (vector takes less memory, so
+    ;; there is less GC), plus `length' comes naturally.  In-place
+    ;; `nreverse' would be faster still, but BODY would be able to see
+    ;; that, even if the modification was undone before we return.
+    `(let* ((,v (vconcat ,list))
+            (,i (length ,v))
+            it it-index)
+       (ignore it it-index)
+       (while (> ,i 0)
+         (setq ,i (1- ,i) it-index ,i it (aref ,v ,i))
+         ,@body))))
+
+(defun -each-r (list fn)
+  "Call FN on each element of LIST in reversed order.
+Return nil; this function is intended for side effects.
+
+Its anaphoric counterpart is `--each-r'."
+  (--each-r list (funcall fn it)))
+
+(defmacro --each-r-while (list pred &rest body)
+  "Eval BODY for each item in reversed LIST, while PRED evals to non-nil.
+Each element of LIST in turn, starting at its end, is bound to
+`it' and its index within LIST to `it-index' before evaluating
+PRED or BODY.  Once an element is reached for which PRED
+evaluates to nil, no further BODY is evaluated.  The return value
+is always nil.
+This is the anaphoric counterpart to `-each-r-while'."
+  (declare (debug (form form body)) (indent 2))
+  (let ((v (make-symbol "vector"))
+        (i (make-symbol "i"))
+        (elt (make-symbol "elt")))
+    `(let* ((,v (vconcat ,list))
+            (,i (length ,v))
+            ,elt it it-index)
+       (ignore it it-index)
+       (while (when (> ,i 0)
+                (setq ,i (1- ,i) it-index ,i)
+                (setq ,elt (aref ,v ,i) it ,elt)
+                ,pred)
+         (setq it-index ,i it ,elt)
+         ,@body))))
+
+(defun -each-r-while (list pred fn)
+  "Call FN on each ITEM in reversed LIST, while (PRED ITEM) is non-nil.
+Once an ITEM is reached for which PRED returns nil, FN is no
+longer called.  Return nil; this function is intended for side
+effects.
+
+Its anaphoric counterpart is `--each-r-while'."
+  (--each-r-while list (funcall pred it) (funcall fn it)))
+
+(defmacro --dotimes (num &rest body)
+  "Evaluate BODY NUM times, presumably for side effects.
+BODY is evaluated with the local variable `it' temporarily bound
+to successive integers running from 0, inclusive, to NUM,
+exclusive.  BODY is not evaluated if NUM is less than 1.
+This is the anaphoric counterpart to `-dotimes'."
+  (declare (debug (form body)) (indent 1))
+  (let ((n (make-symbol "num"))
+        (i (make-symbol "i")))
+    `(let ((,n ,num)
+           (,i 0)
+           it)
+       (ignore it)
+       (while (< ,i ,n)
+         (setq it ,i ,i (1+ ,i))
+         ,@body))))
+
+(defun -dotimes (num fn)
+  "Call FN NUM times, presumably for side effects.
+FN is called with a single argument on successive integers
+running from 0, inclusive, to NUM, exclusive.  FN is not called
+if NUM is less than 1.
+
+This function's anaphoric counterpart is `--dotimes'."
+  (declare (indent 1))
+  (--dotimes num (funcall fn it)))
+
+(defun -map (fn list)
+  "Apply FN to each item in LIST and return the list of results.
+
+This function's anaphoric counterpart is `--map'."
+  (declare (important-return-value t))
+  (mapcar fn list))
+
+(defmacro --map (form list)
+  "Eval FORM for each item in LIST and return the list of results.
+Each element of LIST in turn is bound to `it' before evaluating
+FORM.
+This is the anaphoric counterpart to `-map'."
+  (declare (debug (def-form form)))
+  `(mapcar (lambda (it) (ignore it) ,form) ,list))
+
+(defmacro --reduce-from (form init list)
+  "Accumulate a value by evaluating FORM across LIST.
+This macro is like `--each' (which see), but it additionally
+provides an accumulator variable `acc' which it successively
+binds to the result of evaluating FORM for the current LIST
+element before processing the next element.  For the first
+element, `acc' is initialized with the result of evaluating INIT.
+The return value is the resulting value of `acc'.  If LIST is
+empty, FORM is not evaluated, and the return value is the result
+of INIT.
+This is the anaphoric counterpart to `-reduce-from'."
+  (declare (debug (form form form)))
+  `(let ((acc ,init))
+     (--each ,list (setq acc ,form))
+     acc))
+
+(defun -reduce-from (fn init list)
+  "Reduce the function FN across LIST, starting with INIT.
+Return the result of applying FN to INIT and the first element of
+LIST, then applying FN to that result and the second element,
+etc.  If LIST is empty, return INIT without calling FN.
+
+This function's anaphoric counterpart is `--reduce-from'.
+
+For other folds, see also `-reduce' and `-reduce-r'."
+  (declare (important-return-value t))
+  (--reduce-from (funcall fn acc it) init list))
+
+(defmacro --reduce (form list)
+  "Accumulate a value by evaluating FORM across LIST.
+This macro is like `--reduce-from' (which see), except the first
+element of LIST is taken as INIT.  Thus if LIST contains a single
+item, it is returned without evaluating FORM.  If LIST is empty,
+FORM is evaluated with `it' and `acc' bound to nil.
+This is the anaphoric counterpart to `-reduce'."
+  (declare (debug (form form)))
+  (let ((lv (make-symbol "list-value")))
+    `(let ((,lv ,list))
+       (if ,lv
+           (--reduce-from ,form (car ,lv) (cdr ,lv))
+         ;; Explicit nil binding pacifies lexical "variable left uninitialized"
+         ;; warning.  See issue #377 and upstream https://bugs.gnu.org/47080.
+         (let ((acc nil) (it nil))
+           (ignore acc it)
+           ,form)))))
+
+(defun -reduce (fn list)
+  "Reduce the function FN across LIST.
+Return the result of applying FN to the first two elements of
+LIST, then applying FN to that result and the third element, etc.
+If LIST contains a single element, return it without calling FN.
+If LIST is empty, return the result of calling FN with no
+arguments.
+
+This function's anaphoric counterpart is `--reduce'.
+
+For other folds, see also `-reduce-from' and `-reduce-r'."
+  (declare (important-return-value t))
+  (if list
+      (-reduce-from fn (car list) (cdr list))
+    (funcall fn)))
+
+(defmacro --reduce-r-from (form init list)
+  "Accumulate a value by evaluating FORM across LIST in reverse.
+This macro is like `--reduce-from', except it starts from the end
+of LIST.
+This is the anaphoric counterpart to `-reduce-r-from'."
+  (declare (debug (form form form)))
+  `(let ((acc ,init))
+     (--each-r ,list (setq acc ,form))
+     acc))
+
+(defun -reduce-r-from (fn init list)
+  "Reduce the function FN across LIST in reverse, starting with INIT.
+Return the result of applying FN to the last element of LIST and
+INIT, then applying FN to the second-to-last element and the
+previous result of FN, etc.  That is, the first argument of FN is
+the current element, and its second argument the accumulated
+value.  If LIST is empty, return INIT without calling FN.
+
+This function is like `-reduce-from' but the operation associates
+from the right rather than left.  In other words, it starts from
+the end of LIST and flips the arguments to FN.  Conceptually, it
+is like replacing the conses in LIST with applications of FN, and
+its last link with INIT, and evaluating the resulting expression.
+
+This function's anaphoric counterpart is `--reduce-r-from'.
+
+For other folds, see also `-reduce-r' and `-reduce'."
+  (declare (important-return-value t))
+  (--reduce-r-from (funcall fn it acc) init list))
+
+(defmacro --reduce-r (form list)
+  "Accumulate a value by evaluating FORM across LIST in reverse order.
+This macro is like `--reduce', except it starts from the end of
+LIST.
+This is the anaphoric counterpart to `-reduce-r'."
+  (declare (debug (form form)))
+  `(--reduce ,form (reverse ,list)))
+
+(defun -reduce-r (fn list)
+  "Reduce the function FN across LIST in reverse.
+Return the result of applying FN to the last two elements of
+LIST, then applying FN to the third-to-last element and the
+previous result of FN, etc.  That is, the first argument of FN is
+the current element, and its second argument the accumulated
+value.  If LIST contains a single element, return it without
+calling FN.  If LIST is empty, return the result of calling FN
+with no arguments.
+
+This function is like `-reduce' but the operation associates from
+the right rather than left.  In other words, it starts from the
+end of LIST and flips the arguments to FN.  Conceptually, it is
+like replacing the conses in LIST with applications of FN,
+ignoring its last link, and evaluating the resulting expression.
+
+This function's anaphoric counterpart is `--reduce-r'.
+
+For other folds, see also `-reduce-r-from' and `-reduce'."
+  (declare (important-return-value t))
+  (if list
+      (--reduce-r (funcall fn it acc) list)
+    (funcall fn)))
+
+(defmacro --reductions-from (form init list)
+  "Return a list of FORM's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce-from' (which see) is called with the same
+arguments.
+This is the anaphoric counterpart to `-reductions-from'."
+  (declare (debug (form form form)))
+  `(nreverse
+    (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
+                   (list ,init)
+                   ,list)))
+
+(defun -reductions-from (fn init list)
+  "Return a list of FN's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce-from' (which see) is called with the same
+arguments.
+
+This function's anaphoric counterpart is `--reductions-from'.
+
+For other folds, see also `-reductions' and `-reductions-r'."
+  (declare (important-return-value t))
+  (--reductions-from (funcall fn acc it) init list))
+
+(defmacro --reductions (form list)
+  "Return a list of FORM's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce' (which see) is called with the same arguments.
+This is the anaphoric counterpart to `-reductions'."
+  (declare (debug (form form)))
+  (let ((lv (make-symbol "list-value")))
+    `(let ((,lv ,list))
+       (if ,lv
+           (--reductions-from ,form (car ,lv) (cdr ,lv))
+         ;; Explicit nil binding pacifies lexical "variable left uninitialized"
+         ;; warning.  See issue #377 and upstream https://bugs.gnu.org/47080.
+         (let ((acc nil) (it nil))
+           (ignore acc it)
+           (list ,form))))))
+
+(defun -reductions (fn list)
+  "Return a list of FN's intermediate reductions across LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce' (which see) is called with the same arguments.
+
+This function's anaphoric counterpart is `--reductions'.
+
+For other folds, see also `-reductions' and `-reductions-r'."
+  (declare (important-return-value t))
+  (if list
+      (--reductions-from (funcall fn acc it) (car list) (cdr list))
+    (list (funcall fn))))
+
+(defmacro --reductions-r-from (form init list)
+  "Return a list of FORM's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce-r-from' (which see) is called with the same
+arguments.
+This is the anaphoric counterpart to `-reductions-r-from'."
+  (declare (debug (form form form)))
+  `(--reduce-r-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
+                    (list ,init)
+                    ,list))
+
+(defun -reductions-r-from (fn init list)
+  "Return a list of FN's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce-r-from' (which see) is called with the same
+arguments.
+
+This function's anaphoric counterpart is `--reductions-r-from'.
+
+For other folds, see also `-reductions' and `-reductions-r'."
+  (declare (important-return-value t))
+  (--reductions-r-from (funcall fn it acc) init list))
+
+(defmacro --reductions-r (form list)
+  "Return a list of FORM's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `--reduce-re' (which see) is called with the same arguments.
+This is the anaphoric counterpart to `-reductions-r'."
+  (declare (debug (form list)))
+  (let ((lv (make-symbol "list-value")))
+    `(let ((,lv (reverse ,list)))
+       (if ,lv
+           (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc)
+                          (list (car ,lv))
+                          (cdr ,lv))
+         ;; Explicit nil binding pacifies lexical "variable left uninitialized"
+         ;; warning.  See issue #377 and upstream https://bugs.gnu.org/47080.
+         (let ((acc nil) (it nil))
+           (ignore acc it)
+           (list ,form))))))
+
+(defun -reductions-r (fn list)
+  "Return a list of FN's intermediate reductions across reversed LIST.
+That is, a list of the intermediate values of the accumulator
+when `-reduce-r' (which see) is called with the same arguments.
+
+This function's anaphoric counterpart is `--reductions-r'.
+
+For other folds, see also `-reductions-r-from' and
+`-reductions'."
+  (declare (important-return-value t))
+  (if list
+      (--reductions-r (funcall fn it acc) list)
+    (list (funcall fn))))
+
+(defmacro --filter (form list)
+  "Return a new list of the items in LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-filter'.
+For the opposite operation, see also `--remove'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result")))
+    `(let (,r)
+       (--each ,list (when ,form (push it ,r)))
+       (nreverse ,r))))
+
+(defun -filter (pred list)
+  "Return a new list of the items in LIST for which PRED returns non-nil.
+
+Alias: `-select'.
+
+This function's anaphoric counterpart is `--filter'.
+
+For similar operations, see also `-keep' and `-remove'."
+  (declare (important-return-value t))
+  (--filter (funcall pred it) list))
+
+(defalias '-select '-filter)
+(defalias '--select '--filter)
+
+(defmacro --remove (form list)
+  "Return a new list of the items in LIST for which FORM evals to nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-remove'.
+For the opposite operation, see also `--filter'."
+  (declare (debug (form form)))
+  `(--filter (not ,form) ,list))
+
+(defun -remove (pred list)
+  "Return a new list of the items in LIST for which PRED returns nil.
+
+Alias: `-reject'.
+
+This function's anaphoric counterpart is `--remove'.
+
+For similar operations, see also `-keep' and `-filter'."
+  (declare (important-return-value t))
+  (--remove (funcall pred it) list))
+
+(defalias '-reject '-remove)
+(defalias '--reject '--remove)
+
+(defmacro --remove-first (form list)
+  "Remove the first item from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.  This is a
+non-destructive operation, but only the front of LIST leading up
+to the removed item is a copy; the rest is LIST's original tail.
+If no item is removed, then the result is a complete copy.
+This is the anaphoric counterpart to `-remove-first'."
+  (declare (debug (form form)))
+  (let ((front (make-symbol "front"))
+        (tail (make-symbol "tail")))
+    `(let ((,tail ,list) ,front)
+       (--each-while ,tail (not ,form)
+         (push (pop ,tail) ,front))
+       (if ,tail
+           (nconc (nreverse ,front) (cdr ,tail))
+         (nreverse ,front)))))
+
+(defun -remove-first (pred list)
+  "Remove the first item from LIST for which PRED returns non-nil.
+This is a non-destructive operation, but only the front of LIST
+leading up to the removed item is a copy; the rest is LIST's
+original tail.  If no item is removed, then the result is a
+complete copy.
+
+Alias: `-reject-first'.
+
+This function's anaphoric counterpart is `--remove-first'.
+
+See also `-map-first', `-remove-item', and `-remove-last'."
+  (declare (important-return-value t))
+  (--remove-first (funcall pred it) list))
+
+;; TODO: #'-quoting the macro upsets Emacs 24.
+(defalias '-reject-first #'-remove-first)
+(defalias '--reject-first '--remove-first)
+
+(defmacro --remove-last (form list)
+  "Remove the last item from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' before evaluating
+FORM.  The result is a copy of LIST regardless of whether an
+element is removed.
+This is the anaphoric counterpart to `-remove-last'."
+  (declare (debug (form form)))
+  `(nreverse (--remove-first ,form (reverse ,list))))
+
+(defun -remove-last (pred list)
+  "Remove the last item from LIST for which PRED returns non-nil.
+The result is a copy of LIST regardless of whether an element is
+removed.
+
+Alias: `-reject-last'.
+
+This function's anaphoric counterpart is `--remove-last'.
+
+See also `-map-last', `-remove-item', and `-remove-first'."
+  (declare (important-return-value t))
+  (--remove-last (funcall pred it) list))
+
+(defalias '-reject-last '-remove-last)
+(defalias '--reject-last '--remove-last)
+
+(defalias '-remove-item #'remove
+  "Return a copy of LIST with all occurrences of ITEM removed.
+The comparison is done with `equal'.
+\n(fn ITEM LIST)")
+
+(defmacro --keep (form list)
+  "Eval FORM for each item in LIST and return the non-nil results.
+Like `--filter', but returns the non-nil results of FORM instead
+of the corresponding elements of LIST.  Each element of LIST in
+turn is bound to `it' and its index within LIST to `it-index'
+before evaluating FORM.
+This is the anaphoric counterpart to `-keep'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result"))
+        (m (make-symbol "mapped")))
+    `(let (,r)
+       (--each ,list (let ((,m ,form)) (when ,m (push ,m ,r))))
+       (nreverse ,r))))
+
+(defun -keep (fn list)
+  "Return a new list of the non-nil results of applying FN to each item in LIST.
+Like `-filter', but returns the non-nil results of FN instead of
+the corresponding elements of LIST.
+
+Its anaphoric counterpart is `--keep'."
+  (declare (important-return-value t))
+  (--keep (funcall fn it) list))
+
+(defun -non-nil (list)
+  "Return a copy of LIST with all nil items removed."
+  (declare (side-effect-free t))
+  (--filter it list))
+
+(defmacro --map-indexed (form list)
+  "Eval FORM for each item in LIST and return the list of results.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.  This is like
+`--map', but additionally makes `it-index' available to FORM.
+
+This is the anaphoric counterpart to `-map-indexed'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result")))
+    `(let (,r)
+       (--each ,list
+         (push ,form ,r))
+       (nreverse ,r))))
+
+(defun -map-indexed (fn list)
+  "Apply FN to each index and item in LIST and return the list of results.
+This is like `-map', but FN takes two arguments: the index of the
+current element within LIST, and the element itself.
+
+This function's anaphoric counterpart is `--map-indexed'.
+
+For a side-effecting variant, see also `-each-indexed'."
+  (declare (important-return-value t))
+  (--map-indexed (funcall fn it-index it) list))
+
+(defmacro --map-when (pred rep list)
+  "Anaphoric form of `-map-when'."
+  (declare (debug (form form form)))
+  (let ((r (make-symbol "result")))
+    `(let (,r)
+       (--each ,list (!cons (if ,pred ,rep it) ,r))
+       (nreverse ,r))))
+
+(defun -map-when (pred rep list)
+  "Use PRED to conditionally apply REP to each item in LIST.
+Return a copy of LIST where the items for which PRED returns nil
+are unchanged, and the rest are mapped through the REP function.
+
+Alias: `-replace-where'
+
+See also: `-update-at'"
+  (declare (important-return-value t))
+  (--map-when (funcall pred it) (funcall rep it) list))
+
+(defalias '-replace-where '-map-when)
+(defalias '--replace-where '--map-when)
+
+(defun -map-first (pred rep list)
+  "Use PRED to determine the first item in LIST to call REP on.
+Return a copy of LIST where the first item for which PRED returns
+non-nil is replaced with the result of calling REP on that item.
+
+See also: `-map-when', `-replace-first'"
+  (declare (important-return-value t))
+  (let (front)
+    (while (and list (not (funcall pred (car list))))
+      (push (car list) front)
+      (!cdr list))
+    (if list
+        (-concat (nreverse front) (cons (funcall rep (car list)) (cdr list)))
+      (nreverse front))))
+
+(defmacro --map-first (pred rep list)
+  "Anaphoric form of `-map-first'."
+  (declare (debug (def-form def-form form)))
+  `(-map-first (lambda (it) (ignore it) ,pred)
+               (lambda (it) (ignore it) ,rep)
+               ,list))
+
+(defun -map-last (pred rep list)
+  "Use PRED to determine the last item in LIST to call REP on.
+Return a copy of LIST where the last item for which PRED returns
+non-nil is replaced with the result of calling REP on that item.
+
+See also: `-map-when', `-replace-last'"
+  (declare (important-return-value t))
+  (nreverse (-map-first pred rep (reverse list))))
+
+(defmacro --map-last (pred rep list)
+  "Anaphoric form of `-map-last'."
+  (declare (debug (def-form def-form form)))
+  `(-map-last (lambda (it) (ignore it) ,pred)
+              (lambda (it) (ignore it) ,rep)
+              ,list))
+
+(defun -replace (old new list)
+  "Replace all OLD items in LIST with NEW.
+
+Elements are compared using `equal'.
+
+See also: `-replace-at'"
+  (declare (pure t) (side-effect-free t))
+  (--map-when (equal it old) new list))
+
+(defun -replace-first (old new list)
+  "Replace the first occurrence of OLD with NEW in LIST.
+
+Elements are compared using `equal'.
+
+See also: `-map-first'"
+  (declare (pure t) (side-effect-free t))
+  (--map-first (equal old it) new list))
+
+(defun -replace-last (old new list)
+  "Replace the last occurrence of OLD with NEW in LIST.
+
+Elements are compared using `equal'.
+
+See also: `-map-last'"
+  (declare (pure t) (side-effect-free t))
+  (--map-last (equal old it) new list))
+
+(defmacro --mapcat (form list)
+  "Anaphoric form of `-mapcat'."
+  (declare (debug (form form)))
+  `(apply #'append (--map ,form ,list)))
+
+(defun -mapcat (fn list)
+  "Return the concatenation of the result of mapping FN over LIST.
+Thus function FN should return a list."
+  (declare (important-return-value t))
+  (--mapcat (funcall fn it) list))
+
+(defmacro --iterate (form init n)
+  "Anaphoric version of `-iterate'."
+  (declare (debug (form form form)))
+  (let ((res (make-symbol "result"))
+        (len (make-symbol "n")))
+    `(let ((,len ,n))
+       (when (> ,len 0)
+         (let* ((it ,init)
+                (,res (list it)))
+           (dotimes (_ (1- ,len))
+             (push (setq it ,form) ,res))
+           (nreverse ,res))))))
+
+(defun -iterate (fun init n)
+  "Return a list of iterated applications of FUN to INIT.
+
+This means a list of the form:
+
+  (INIT (FUN INIT) (FUN (FUN INIT)) ...)
+
+N is the length of the returned list."
+  (declare (important-return-value t))
+  (--iterate (funcall fun it) init n))
+
+(defun -flatten (l)
+  "Take a nested list L and return its contents as a single, flat list.
+
+Note that because nil represents a list of zero elements (an
+empty list), any mention of nil in L will disappear after
+flattening.  If you need to preserve nils, consider `-flatten-n'
+or map them to some unique symbol and then map them back.
+
+Conses of two atoms are considered \"terminals\", that is, they
+aren't flattened further.
+
+See also: `-flatten-n'"
+  (declare (pure t) (side-effect-free t))
+  (if (and (listp l) (listp (cdr l)))
+      (-mapcat '-flatten l)
+    (list l)))
+
+(defun -flatten-n (num list)
+  "Flatten NUM levels of a nested LIST.
+
+See also: `-flatten'"
+  (declare (pure t) (side-effect-free t))
+  (dotimes (_ num)
+    (setq list (apply #'append (mapcar #'-list list))))
+  list)
+
+(defalias '-concat #'append
+  "Concatenate all SEQUENCES and make the result a list.
+The result is a list whose elements are the elements of all the arguments.
+Each argument may be a list, vector or string.
+
+All arguments except the last argument are copied.  The last argument
+is just used as the tail of the new list.  If the last argument is not
+a list, this results in a dotted list.
+
+As an exception, if all the arguments except the last are nil, and the
+last argument is not a list, the return value is that last argument
+unaltered, not a list.
+
+\(fn &rest SEQUENCES)")
+
+(defalias '-copy #'copy-sequence
+  "Create a shallow copy of LIST.
+The elements of LIST are not copied; they are shared with the original.
+\n(fn LIST)")
+
+(defmacro --splice (pred form list)
+  "Splice lists generated by FORM in place of items satisfying PRED in LIST.
+
+Evaluate PRED for each element of LIST in turn bound to `it'.
+Whenever the result of PRED is nil, leave that `it' is-is.
+Otherwise, evaluate FORM with the same `it' binding still in
+place.  The result should be a (possibly empty) list of items to
+splice in place of `it' in LIST.
+
+This can be useful as an alternative to the `,@' construct in a
+`\\=`' structure, in case you need to splice several lists at
+marked positions (for example with keywords).
+
+This is the anaphoric counterpart to `-splice'."
+  (declare (debug (form form form)))
+  (let ((r (make-symbol "result")))
+    `(let (,r)
+       (--each ,list
+         (if ,pred
+             (--each ,form (push it ,r))
+           (push it ,r)))
+       (nreverse ,r))))
+
+(defun -splice (pred fun list)
+  "Splice lists generated by FUN in place of items satisfying PRED in LIST.
+
+Call PRED on each element of LIST.  Whenever the result of PRED
+is nil, leave that `it' as-is.  Otherwise, call FUN on the same
+`it' that satisfied PRED.  The result should be a (possibly
+empty) list of items to splice in place of `it' in LIST.
+
+This can be useful as an alternative to the `,@' construct in a
+`\\=`' structure, in case you need to splice several lists at
+marked positions (for example with keywords).
+
+This function's anaphoric counterpart is `--splice'.
+
+See also: `-splice-list', `-insert-at'."
+  (declare (important-return-value t))
+  (--splice (funcall pred it) (funcall fun it) list))
+
+(defun -splice-list (pred new-list list)
+  "Splice NEW-LIST in place of elements matching PRED in LIST.
+
+See also: `-splice', `-insert-at'"
+  (declare (important-return-value t))
+  (-splice pred (lambda (_) new-list) list))
+
+(defmacro --splice-list (pred new-list list)
+  "Anaphoric form of `-splice-list'."
+  (declare (debug (def-form form form)))
+  `(-splice-list (lambda (it) (ignore it) ,pred) ,new-list ,list))
+
+(defun -cons* (&rest args)
+  "Make a new list from the elements of ARGS.
+The last 2 elements of ARGS are used as the final cons of the
+result, so if the final element of ARGS is not a list, the result
+is a dotted list.  With no ARGS, return nil."
+  (declare (side-effect-free t))
+  (let* ((len (length args))
+         (tail (nthcdr (- len 2) args))
+         (last (cdr tail)))
+    (if (null last)
+        (car args)
+      (setcdr tail (car last))
+      args)))
+
+(defun -snoc (list elem &rest elements)
+  "Append ELEM to the end of the list.
+
+This is like `cons', but operates on the end of list.
+
+If any ELEMENTS are given, append them to the list as well."
+  (declare (side-effect-free t))
+  (-concat list (list elem) elements))
+
+(defmacro --first (form list)
+  "Return the first item in LIST for which FORM evals to non-nil.
+Return nil if no such element is found.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-first'."
+  (declare (debug (form form)))
+  (let ((n (make-symbol "needle")))
+    `(let (,n)
+       (--each-while ,list (or (not ,form)
+                               (ignore (setq ,n it))))
+       ,n)))
+
+(defun -first (pred list)
+  "Return the first item in LIST for which PRED returns non-nil.
+Return nil if no such element is found.
+
+To get the first item in the list no questions asked,
+use `-first-item'.
+
+Alias: `-find'.
+
+This function's anaphoric counterpart is `--first'."
+  (declare (important-return-value t))
+  (--first (funcall pred it) list))
+
+(defalias '-find #'-first)
+(defalias '--find '--first)
+
+(defmacro --some (form list)
+  "Return non-nil if FORM evals to non-nil for at least one item in LIST.
+If so, return the first such result of FORM.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-some'."
+  (declare (debug (form form)))
+  (let ((n (make-symbol "needle")))
+    `(let (,n)
+       (--each-while ,list (not (setq ,n ,form)))
+       ,n)))
+
+(defun -some (pred list)
+  "Return (PRED x) for the first LIST item where (PRED x) is non-nil, else nil.
+
+Alias: `-any'.
+
+This function's anaphoric counterpart is `--some'."
+  (declare (important-return-value t))
+  (--some (funcall pred it) list))
+
+(defalias '-any '-some)
+(defalias '--any '--some)
+
+(defmacro --every (form list)
+  "Return non-nil if FORM evals to non-nil for all items in LIST.
+If so, return the last such result of FORM.  Otherwise, once an
+item is reached for which FORM yields nil, return nil without
+evaluating FORM for any further LIST elements.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+
+This macro is like `--every-p', but on success returns the last
+non-nil result of FORM instead of just t.
+
+This is the anaphoric counterpart to `-every'."
+  (declare (debug (form form)))
+  (let ((a (make-symbol "all")))
+    `(let ((,a t))
+       (--each-while ,list (setq ,a ,form))
+       ,a)))
+
+(defun -every (pred list)
+  "Return non-nil if PRED returns non-nil for all items in LIST.
+If so, return the last such result of PRED.  Otherwise, once an
+item is reached for which PRED returns nil, return nil without
+calling PRED on any further LIST elements.
+
+This function is like `-every-p', but on success returns the last
+non-nil result of PRED instead of just t.
+
+This function's anaphoric counterpart is `--every'."
+  (declare (important-return-value t))
+  (--every (funcall pred it) list))
+
+(defmacro --last (form list)
+  "Anaphoric form of `-last'."
+  (declare (debug (form form)))
+  (let ((n (make-symbol "needle")))
+    `(let (,n)
+       (--each ,list
+         (when ,form (setq ,n it)))
+       ,n)))
+
+(defun -last (pred list)
+  "Return the last x in LIST where (PRED x) is non-nil, else nil."
+  (declare (important-return-value t))
+  (--last (funcall pred it) list))
+
+(defalias '-first-item #'car
+  "Return the first item of LIST, or nil on an empty list.
+
+See also: `-second-item', `-last-item', etc.
+
+\(fn LIST)")
+
+;; Ensure that calls to `-first-item' are compiled to a single opcode,
+;; just like `car'.
+(put '-first-item 'byte-opcode 'byte-car)
+(put '-first-item 'byte-compile 'byte-compile-one-arg)
+(put '-first-item 'pure t)
+(put '-first-item 'side-effect-free t)
+
+(defalias '-second-item #'cadr
+  "Return the second item of LIST, or nil if LIST is too short.
+
+See also: `-first-item', `-third-item', etc.
+
+\(fn LIST)")
+
+(put '-second-item 'pure t)
+(put '-second-item 'side-effect-free t)
+
+(defalias '-third-item
+  (if (fboundp 'caddr)
+      #'caddr
+    (lambda (list) (car (cddr list))))
+  "Return the third item of LIST, or nil if LIST is too short.
+
+See also: `-second-item', `-fourth-item', etc.
+
+\(fn LIST)")
+
+(put '-third-item 'pure t)
+(put '-third-item 'side-effect-free t)
+
+(defalias '-fourth-item
+  (if (fboundp 'cadddr)
+      #'cadddr
+    (lambda (list) (cadr (cddr list))))
+  "Return the fourth item of LIST, or nil if LIST is too short.
+
+See also: `-third-item', `-fifth-item', etc.
+
+\(fn LIST)")
+
+(put '-fourth-item 'pure t)
+(put '-fourth-item 'side-effect-free t)
+
+(defun -fifth-item (list)
+  "Return the fifth item of LIST, or nil if LIST is too short.
+
+See also: `-fourth-item', `-last-item', etc."
+  (declare (pure t) (side-effect-free t))
+  (car (cddr (cddr list))))
+
+(defun -last-item (list)
+  "Return the last item of LIST, or nil on an empty list.
+
+See also: `-first-item', etc."
+  (declare (pure t) (side-effect-free t))
+  (car (last list)))
+
+(static-if (fboundp 'gv-define-setter)
+    (gv-define-setter -last-item (val x) `(setcar (last ,x) ,val))
+  (defsetf -last-item (x) (val) `(setcar (last ,x) ,val)))
+
+(defun -butlast (list)
+  "Return a list of all items in list except for the last."
+  ;; no alias as we don't want magic optional argument
+  (declare (pure t) (side-effect-free t))
+  (butlast list))
+
+(defmacro --count (pred list)
+  "Anaphoric form of `-count'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result")))
+    `(let ((,r 0))
+       (--each ,list (when ,pred (setq ,r (1+ ,r))))
+       ,r)))
+
+(defun -count (pred list)
+  "Counts the number of items in LIST where (PRED item) is non-nil."
+  (declare (important-return-value t))
+  (--count (funcall pred it) list))
+
+(defun ---truthy? (obj)
+  "Return OBJ as a boolean value (t or nil)."
+  (declare (pure t) (side-effect-free error-free))
+  (and obj t))
+
+(defmacro --any? (form list)
+  "Anaphoric form of `-any?'."
+  (declare (debug (form form)))
+  `(and (--some ,form ,list) t))
+
+(defun -any? (pred list)
+  "Return t if (PRED X) is non-nil for any X in LIST, else nil.
+
+Alias: `-any-p', `-some?', `-some-p'"
+  (declare (important-return-value t))
+  (--any? (funcall pred it) list))
+
+(defalias '-some? '-any?)
+(defalias '--some? '--any?)
+(defalias '-any-p '-any?)
+(defalias '--any-p '--any?)
+(defalias '-some-p '-any?)
+(defalias '--some-p '--any?)
+
+(defmacro --all? (form list)
+  "Return t if FORM evals to non-nil for all items in LIST.
+Otherwise, once an item is reached for which FORM yields nil,
+return nil without evaluating FORM for any further LIST elements.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+
+The similar macro `--every' is more widely useful, since it
+returns the last non-nil result of FORM instead of just t on
+success.
+
+Alias: `--all-p', `--every-p', `--every?'.
+
+This is the anaphoric counterpart to `-all?'."
+  (declare (debug (form form)))
+  `(and (--every ,form ,list) t))
+
+(defun -all? (pred list)
+  "Return t if (PRED X) is non-nil for all X in LIST, else nil.
+In the latter case, stop after the first X for which (PRED X) is
+nil, without calling PRED on any subsequent elements of LIST.
+
+The similar function `-every' is more widely useful, since it
+returns the last non-nil result of PRED instead of just t on
+success.
+
+Alias: `-all-p', `-every-p', `-every?'.
+
+This function's anaphoric counterpart is `--all?'."
+  (declare (important-return-value t))
+  (--all? (funcall pred it) list))
+
+(defalias '-every? '-all?)
+(defalias '--every? '--all?)
+(defalias '-all-p '-all?)
+(defalias '--all-p '--all?)
+(defalias '-every-p '-all?)
+(defalias '--every-p '--all?)
+
+(defmacro --none? (form list)
+  "Anaphoric form of `-none?'."
+  (declare (debug (form form)))
+  `(--all? (not ,form) ,list))
+
+(defun -none? (pred list)
+  "Return t if (PRED X) is nil for all X in LIST, else nil.
+
+Alias: `-none-p'"
+  (declare (important-return-value t))
+  (--none? (funcall pred it) list))
+
+(defalias '-none-p '-none?)
+(defalias '--none-p '--none?)
+
+(defmacro --only-some? (form list)
+  "Anaphoric form of `-only-some?'."
+  (declare (debug (form form)))
+  (let ((y (make-symbol "yes"))
+        (n (make-symbol "no")))
+    `(let (,y ,n)
+       (--each-while ,list (not (and ,y ,n))
+         (if ,form (setq ,y t) (setq ,n t)))
+       (---truthy? (and ,y ,n)))))
+
+(defun -only-some? (pred list)
+  "Return t if different LIST items both satisfy and do not satisfy PRED.
+That is, if PRED returns both nil for at least one item, and
+non-nil for at least one other item in LIST.  Return nil if all
+items satisfy the predicate or none of them do.
+
+Alias: `-only-some-p'"
+  (declare (important-return-value t))
+  (--only-some? (funcall pred it) list))
+
+(defalias '-only-some-p '-only-some?)
+(defalias '--only-some-p '--only-some?)
+
+(defun -slice (list from &optional to step)
+  "Return copy of LIST, starting from index FROM to index TO.
+
+FROM or TO may be negative.  These values are then interpreted
+modulo the length of the list.
+
+If STEP is a number, only each STEPth item in the resulting
+section is returned.  Defaults to 1."
+  (declare (side-effect-free t))
+  (let ((length (length list))
+        (new-list nil))
+    ;; to defaults to the end of the list
+    (setq to (or to length))
+    (setq step (or step 1))
+    ;; handle negative indices
+    (when (< from 0)
+      (setq from (mod from length)))
+    (when (< to 0)
+      (setq to (mod to length)))
+
+    ;; iterate through the list, keeping the elements we want
+    (--each-while list (< it-index to)
+      (when (and (>= it-index from)
+                 (= (mod (- from it-index) step) 0))
+        (push it new-list)))
+    (nreverse new-list)))
+
+(defmacro --take-while (form list)
+  "Take successive items from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.  Return a new
+list of the successive elements from the start of LIST for which
+FORM evaluates to non-nil.
+This is the anaphoric counterpart to `-take-while'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result")))
+    `(let (,r)
+       (--each-while ,list ,form (push it ,r))
+       (nreverse ,r))))
+
+(defun -take-while (pred list)
+  "Take successive items from LIST for which PRED returns non-nil.
+PRED is a function of one argument.  Return a new list of the
+successive elements from the start of LIST for which PRED returns
+non-nil.
+
+This function's anaphoric counterpart is `--take-while'.
+
+For another variant, see also `-drop-while'."
+  (declare (important-return-value t))
+  (--take-while (funcall pred it) list))
+
+(defmacro --drop-while (form list)
+  "Drop successive items from LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.  Return the
+tail (not a copy) of LIST starting from its first element for
+which FORM evaluates to nil.
+This is the anaphoric counterpart to `-drop-while'."
+  (declare (debug (form form)))
+  (let ((l (make-symbol "list")))
+    `(let ((,l ,list))
+       (--each-while ,l ,form (pop ,l))
+       ,l)))
+
+(defun -drop-while (pred list)
+  "Drop successive items from LIST for which PRED returns non-nil.
+PRED is a function of one argument.  Return the tail (not a copy)
+of LIST starting from its first element for which PRED returns
+nil.
+
+This function's anaphoric counterpart is `--drop-while'.
+
+For another variant, see also `-take-while'."
+  (declare (important-return-value t))
+  (--drop-while (funcall pred it) list))
+
+;; Added in Emacs 29.
+(static-if (fboundp 'take)
+    (defun dash--take (n list)
+      "Return the first N elements of LIST.
+Like `take', but ensure result is fresh."
+      (let ((prefix (take n list)))
+        (if (eq prefix list)
+            ;; If same list is returned, make a copy.
+            (copy-sequence prefix)
+          prefix))))
+
+(defun -take (n list)
+  "Return a copy of the first N items in LIST.
+Return a copy of LIST if it contains N items or fewer.
+Return nil if N is zero or less.
+
+See also: `-take-last'."
+  (declare (side-effect-free t))
+  (static-if (fboundp 'dash--take)
+      (dash--take n list)
+    (--take-while (< it-index n) list)))
+
+(defun -take-last (n list)
+  "Return a copy of the last N items of LIST in order.
+Return a copy of LIST if it contains N items or fewer.
+Return nil if N is zero or less.
+
+See also: `-take'."
+  (declare (side-effect-free t))
+  (copy-sequence (last list n)))
+
+(defalias '-drop #'nthcdr
+  "Return the tail (not a copy) of LIST without the first N items.
+Return nil if LIST contains N items or fewer.
+Return LIST if N is zero or less.
+
+For another variant, see also `-drop-last'.
+\n(fn N LIST)")
+
+(defun -drop-last (n list)
+  "Return a copy of LIST without its last N items.
+Return a copy of LIST if N is zero or less.
+Return nil if LIST contains N items or fewer.
+
+See also: `-drop'."
+  (declare (side-effect-free t))
+  (static-if (fboundp 'dash--take)
+      (dash--take (- (length list) n) list)
+    (nbutlast (copy-sequence list) n)))
+
+(defun -split-at (n list)
+  "Split LIST into two sublists after the Nth element.
+The result is a list of two elements (TAKE DROP) where TAKE is a
+new list of the first N elements of LIST, and DROP is the
+remaining elements of LIST (not a copy).  TAKE and DROP are like
+the results of `-take' and `-drop', respectively, but the split
+is done in a single list traversal."
+  (declare (side-effect-free t))
+  (let (result)
+    (--each-while list (< it-index n)
+      (push (pop list) result))
+    (list (nreverse result) list)))
+
+(defun -rotate (n list)
+  "Rotate LIST N places to the right (left if N is negative).
+The time complexity is O(n)."
+  (declare (pure t) (side-effect-free t))
+  (cond ((null list) ())
+        ((zerop n) (copy-sequence list))
+        ((let* ((len (length list))
+                (n-mod-len (mod n len))
+                (new-tail-len (- len n-mod-len)))
+           (append (nthcdr new-tail-len list) (-take new-tail-len list))))))
+
+(defun -insert-at (n x list)
+  "Return a list with X inserted into LIST at position N.
+
+See also: `-splice', `-splice-list'"
+  (declare (pure t) (side-effect-free t))
+  (let ((split-list (-split-at n list)))
+    (nconc (car split-list) (cons x (cadr split-list)))))
+
+(defun -replace-at (n x list)
+  "Return a list with element at Nth position in LIST replaced with X.
+
+See also: `-replace'"
+  (declare (pure t) (side-effect-free t))
+  (let ((split-list (-split-at n list)))
+    (nconc (car split-list) (cons x (cdr (cadr split-list))))))
+
+(defun -update-at (n func list)
+  "Use FUNC to update the Nth element of LIST.
+Return a copy of LIST where the Nth element is replaced with the
+result of calling FUNC on it.
+
+See also: `-map-when'"
+  (declare (important-return-value t))
+  (let ((split-list (-split-at n list)))
+    (nconc (car split-list)
+           (cons (funcall func (car (cadr split-list)))
+                 (cdr (cadr split-list))))))
+
+(defmacro --update-at (n form list)
+  "Anaphoric version of `-update-at'."
+  (declare (debug (form def-form form)))
+  `(-update-at ,n (lambda (it) (ignore it) ,form) ,list))
+
+(defun -remove-at (n list)
+  "Return LIST with its element at index N removed.
+That is, remove any element selected as (nth N LIST) from LIST
+and return the result.
+
+This is a non-destructive operation: parts of LIST (but not
+necessarily all of it) are copied as needed to avoid
+destructively modifying it.
+
+See also: `-remove-at-indices', `-remove'."
+  (declare (pure t) (side-effect-free t))
+  (if (zerop n)
+      (cdr list)
+    (--remove-first (= it-index n) list)))
+
+(defun -remove-at-indices (indices list)
+  "Return LIST with its elements at INDICES removed.
+That is, for each index I in INDICES, remove any element selected
+as (nth I LIST) from LIST.
+
+This is a non-destructive operation: parts of LIST (but not
+necessarily all of it) are copied as needed to avoid
+destructively modifying it.
+
+See also: `-remove-at', `-remove'."
+  (declare (pure t) (side-effect-free t))
+  (setq indices (--drop-while (< it 0) (-sort #'< indices)))
+  (let ((i (pop indices)) res)
+    (--each-while list i
+      (pop list)
+      (if (/= it-index i)
+          (push it res)
+        (while (and indices (= (car indices) i))
+          (pop indices))
+        (setq i (pop indices))))
+    (nconc (nreverse res) list)))
+
+(defmacro --split-with (pred list)
+  "Anaphoric form of `-split-with'."
+  (declare (debug (form form)))
+  (let ((l (make-symbol "list"))
+        (r (make-symbol "result"))
+        (c (make-symbol "continue")))
+    `(let ((,l ,list)
+           (,r nil)
+           (,c t))
+       (while (and ,l ,c)
+         (let ((it (car ,l)))
+           (if (not ,pred)
+               (setq ,c nil)
+             (!cons it ,r)
+             (!cdr ,l))))
+       (list (nreverse ,r) ,l))))
+
+(defun -split-with (pred list)
+  "Split LIST into a prefix satisfying PRED, and the rest.
+The first sublist is the prefix of LIST with successive elements
+satisfying PRED, and the second sublist is the remaining elements
+that do not.  The result is like performing
+
+  ((-take-while PRED LIST) (-drop-while PRED LIST))
+
+but in no more than a single pass through LIST."
+  (declare (important-return-value t))
+  (--split-with (funcall pred it) list))
+
+(defmacro -split-on (item list)
+  "Split the LIST each time ITEM is found.
+
+Unlike `-partition-by', the ITEM is discarded from the results.
+Empty lists are also removed from the result.
+
+Comparison is done by `equal'.
+
+See also `-split-when'"
+  (declare (debug (def-form form)))
+  `(-split-when (lambda (it) (equal it ,item)) ,list))
+
+(defmacro --split-when (form list)
+  "Anaphoric version of `-split-when'."
+  (declare (debug (def-form form)))
+  `(-split-when (lambda (it) (ignore it) ,form) ,list))
+
+(defun -split-when (fn list)
+  "Split the LIST on each element where FN returns non-nil.
+
+Unlike `-partition-by', the \"matched\" element is discarded from
+the results.  Empty lists are also removed from the result.
+
+This function can be thought of as a generalization of
+`split-string'."
+  (declare (important-return-value t))
+  (let (r s)
+    (while list
+      (if (not (funcall fn (car list)))
+          (push (car list) s)
+        (when s (push (nreverse s) r))
+        (setq s nil))
+      (!cdr list))
+    (when s (push (nreverse s) r))
+    (nreverse r)))
+
+(defmacro --separate (form list)
+  "Anaphoric form of `-separate'."
+  (declare (debug (form form)))
+  (let ((y (make-symbol "yes"))
+        (n (make-symbol "no")))
+    `(let (,y ,n)
+       (--each ,list (if ,form (!cons it ,y) (!cons it ,n)))
+       (list (nreverse ,y) (nreverse ,n)))))
+
+(defun -separate (pred list)
+  "Split LIST into two sublists based on whether items satisfy PRED.
+The result is like performing
+
+  ((-filter PRED LIST) (-remove PRED LIST))
+
+but in a single pass through LIST."
+  (declare (important-return-value t))
+  (--separate (funcall pred it) list))
+
+(defun dash--partition-all-in-steps-reversed (n step list)
+  "Like `-partition-all-in-steps', but the result is reversed."
+  (when (< step 1)
+    (signal 'wrong-type-argument
+            `("Step size < 1 results in juicy infinite loops" ,step)))
+  (let (result)
+    (while list
+      (push (-take n list) result)
+      (setq list (nthcdr step list)))
+    result))
+
+(defun -partition-all-in-steps (n step list)
+  "Partition LIST into sublists of length N that are STEP items apart.
+Adjacent groups may overlap if N exceeds the STEP stride.
+Trailing groups may contain less than N items."
+  (declare (pure t) (side-effect-free t))
+  (nreverse (dash--partition-all-in-steps-reversed n step list)))
+
+(defun -partition-in-steps (n step list)
+  "Partition LIST into sublists of length N that are STEP items apart.
+Like `-partition-all-in-steps', but if there are not enough items
+to make the last group N-sized, those items are discarded."
+  (declare (pure t) (side-effect-free t))
+  (let ((result (dash--partition-all-in-steps-reversed n step list)))
+    (while (and result (< (length (car result)) n))
+      (pop result))
+    (nreverse result)))
+
+(defun -partition-all (n list)
+  "Return a new list with the items in LIST grouped into N-sized sublists.
+The last group may contain less than N items."
+  (declare (pure t) (side-effect-free t))
+  (-partition-all-in-steps n n list))
+
+(defun -partition (n list)
+  "Return a new list with the items in LIST grouped into N-sized sublists.
+If there are not enough items to make the last group N-sized,
+those items are discarded."
+  (declare (pure t) (side-effect-free t))
+  (-partition-in-steps n n list))
+
+(defmacro --partition-by (form list)
+  "Anaphoric form of `-partition-by'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result"))
+        (s (make-symbol "sublist"))
+        (v (make-symbol "value"))
+        (n (make-symbol "new-value"))
+        (l (make-symbol "list")))
+    `(let ((,l ,list))
+       (when ,l
+         (let* ((,r nil)
+                (it (car ,l))
+                (,s (list it))
+                (,v ,form)
+                (,l (cdr ,l)))
+           (while ,l
+             (let* ((it (car ,l))
+                    (,n ,form))
+               (unless (equal ,v ,n)
+                 (!cons (nreverse ,s) ,r)
+                 (setq ,s nil)
+                 (setq ,v ,n))
+               (!cons it ,s)
+               (!cdr ,l)))
+           (!cons (nreverse ,s) ,r)
+           (nreverse ,r))))))
+
+(defun -partition-by (fn list)
+  "Apply FN to each item in LIST, splitting it each time FN returns a new value."
+  (declare (important-return-value t))
+  (--partition-by (funcall fn it) list))
+
+(defmacro --partition-by-header (form list)
+  "Anaphoric form of `-partition-by-header'."
+  (declare (debug (form form)))
+  (let ((r (make-symbol "result"))
+        (s (make-symbol "sublist"))
+        (h (make-symbol "header-value"))
+        (b (make-symbol "seen-body?"))
+        (n (make-symbol "new-value"))
+        (l (make-symbol "list")))
+    `(let ((,l ,list))
+       (when ,l
+         (let* ((,r nil)
+                (it (car ,l))
+                (,s (list it))
+                (,h ,form)
+                (,b nil)
+                (,l (cdr ,l)))
+           (while ,l
+             (let* ((it (car ,l))
+                    (,n ,form))
+               (if (equal ,h ,n)
+                   (when ,b
+                     (!cons (nreverse ,s) ,r)
+                     (setq ,s nil)
+                     (setq ,b nil))
+                 (setq ,b t))
+               (!cons it ,s)
+               (!cdr ,l)))
+           (!cons (nreverse ,s) ,r)
+           (nreverse ,r))))))
+
+(defun -partition-by-header (fn list)
+  "Apply FN to the first item in LIST. That is the header
+value. Apply FN to each item in LIST, splitting it each time FN
+returns the header value, but only after seeing at least one
+other value (the body)."
+  (declare (important-return-value t))
+  (--partition-by-header (funcall fn it) list))
+
+(defmacro --partition-after-pred (form list)
+  "Partition LIST after each element for which FORM evaluates to non-nil.
+Each element of LIST in turn is bound to `it' before evaluating
+FORM.
+
+This is the anaphoric counterpart to `-partition-after-pred'."
+  (let ((l (make-symbol "list"))
+        (r (make-symbol "result"))
+        (s (make-symbol "sublist")))
+    `(let ((,l ,list) ,r ,s)
+       (when ,l
+         (--each ,l
+           (push it ,s)
+           (when ,form
+             (push (nreverse ,s) ,r)
+             (setq ,s ())))
+         (when ,s
+           (push (nreverse ,s) ,r))
+         (nreverse ,r)))))
+
+(defun -partition-after-pred (pred list)
+  "Partition LIST after each element for which PRED returns non-nil.
+
+This function's anaphoric counterpart is `--partition-after-pred'."
+  (declare (important-return-value t))
+  (--partition-after-pred (funcall pred it) list))
+
+(defun -partition-before-pred (pred list)
+  "Partition directly before each time PRED is true on an element of LIST."
+  (declare (important-return-value t))
+  (nreverse (-map #'reverse
+                  (-partition-after-pred pred (reverse list)))))
+
+(defun -partition-after-item (item list)
+  "Partition directly after each time ITEM appears in LIST."
+  (declare (pure t) (side-effect-free t))
+  (-partition-after-pred (lambda (ele) (equal ele item))
+                         list))
+
+(defun -partition-before-item (item list)
+  "Partition directly before each time ITEM appears in LIST."
+  (declare (pure t) (side-effect-free t))
+  (-partition-before-pred (lambda (ele) (equal ele item))
+                          list))
+
+(defmacro --group-by (form list)
+  "Anaphoric form of `-group-by'."
+  (declare (debug t))
+  (let ((n (make-symbol "n"))
+        (k (make-symbol "k"))
+        (grp (make-symbol "grp")))
+    `(nreverse
+      (-map
+       (lambda (,n)
+         (cons (car ,n)
+               (nreverse (cdr ,n))))
+       (--reduce-from
+        (let* ((,k (,@form))
+               (,grp (assoc ,k acc)))
+          (if ,grp
+              (setcdr ,grp (cons it (cdr ,grp)))
+            (push
+             (list ,k it)
+             acc))
+          acc)
+        nil ,list)))))
+
+(defun -group-by (fn list)
+  "Separate LIST into an alist whose keys are FN applied to the
+elements of LIST.  Keys are compared by `equal'."
+  (declare (important-return-value t))
+  (--group-by (funcall fn it) list))
+
+(defun -interpose (sep list)
+  "Return a new list of all elements in LIST separated by SEP."
+  (declare (side-effect-free t))
+  (let (result)
+    (when list
+      (!cons (car list) result)
+      (!cdr list))
+    (while list
+      (setq result (cons (car list) (cons sep result)))
+      (!cdr list))
+    (nreverse result)))
+
+(defun -interleave (&rest lists)
+  "Return a new list of the first item in each list, then the second etc."
+  (declare (side-effect-free t))
+  (when lists
+    (let (result)
+      (while (-none? 'null lists)
+        (--each lists (!cons (car it) result))
+        (setq lists (-map 'cdr lists)))
+      (nreverse result))))
+
+(defmacro --zip-with (form list1 list2)
+  "Zip LIST1 and LIST2 into a new list according to FORM.
+That is, evaluate FORM for each item pair from the two lists, and
+return the list of results.  The result is as long as the shorter
+list.
+
+Each element of LIST1 and each element of LIST2 in turn are bound
+pairwise to `it' and `other', respectively, and their index
+within the list to `it-index', before evaluating FORM.
+
+This is the anaphoric counterpart to `-zip-with'."
+  (declare (debug (form form form)))
+  (let ((r (make-symbol "result"))
+        (l2 (make-symbol "list2")))
+    `(let ((,l2 ,list2) ,r)
+       (--each-while ,list1 ,l2
+         (let ((other (pop ,l2)))
+           (ignore other)
+           (push ,form ,r)))
+       (nreverse ,r))))
+
+(defun -zip-with (fn list1 list2)
+  "Zip LIST1 and LIST2 into a new list using the function FN.
+That is, apply FN pairwise taking as first argument the next
+element of LIST1 and as second argument the next element of LIST2
+at the corresponding position.  The result is as long as the
+shorter list.
+
+This function's anaphoric counterpart is `--zip-with'.
+
+For other zips, see also `-zip-lists' and `-zip-fill'."
+  (declare (important-return-value t))
+  (--zip-with (funcall fn it other) list1 list2))
+
+(defun -zip-lists (&rest lists)
+  "Zip LISTS together.
+
+Group the head of each list, followed by the second element of
+each list, and so on.  The number of returned groupings is equal
+to the length of the shortest input list, and the length of each
+grouping is equal to the number of input LISTS.
+
+The return value is always a list of proper lists, in contrast to
+`-zip' which returns a list of dotted pairs when only two input
+LISTS are provided.
+
+See also: `-zip-pair'."
+  (declare (pure t) (side-effect-free t))
+  (when lists
+    (let (results)
+      (while (--every it lists)
+        (push (mapcar #'car lists) results)
+        (setq lists (mapcar #'cdr lists)))
+      (nreverse results))))
+
+(defun -zip-lists-fill (fill-value &rest lists)
+  "Zip LISTS together, padding shorter lists with FILL-VALUE.
+This is like `-zip-lists' (which see), except it retains all
+elements at positions beyond the end of the shortest list.  The
+number of returned groupings is equal to the length of the
+longest input list, and the length of each grouping is equal to
+the number of input LISTS."
+  (declare (pure t) (side-effect-free t))
+  (when lists
+    (let (results)
+      (while (--some it lists)
+        (push (--map (if it (car it) fill-value) lists) results)
+        (setq lists (mapcar #'cdr lists)))
+      (nreverse results))))
+
+(defun -unzip-lists (lists)
+  "Unzip LISTS.
+
+This works just like `-zip-lists' (which see), but takes a list
+of lists instead of a variable number of arguments, such that
+
+  (-unzip-lists (-zip-lists ARGS...))
+
+is identity (given that the lists comprising ARGS are of the same
+length)."
+  (declare (pure t) (side-effect-free t))
+  (apply #'-zip-lists lists))
+
+(defalias 'dash--length=
+  (if (fboundp 'length=)
+      #'length=
+    (lambda (list length)
+      (cond ((< length 0) nil)
+            ((zerop length) (null list))
+            ((let ((last (nthcdr (1- length) list)))
+               (and last (null (cdr last))))))))
+  "Return non-nil if LIST is of LENGTH.
+This is a compatibility shim for `length=' in Emacs 28.
+\n(fn LIST LENGTH)")
+
+(defun dash--zip-lists-or-pair (_form &rest lists)
+  "Return a form equivalent to applying `-zip' to LISTS.
+This `compiler-macro' warns about discouraged `-zip' usage and
+delegates to `-zip-lists' or `-zip-pair' depending on the number
+of LISTS."
+  (if (not (dash--length= lists 2))
+      (cons #'-zip-lists lists)
+    (let ((pair (cons #'-zip-pair lists))
+          (msg "Use -zip-pair instead of -zip to get a list of pairs"))
+      (if (fboundp 'macroexp-warn-and-return)
+          (macroexp-warn-and-return msg pair)
+        (message msg)
+        pair))))
+
+(defun -zip (&rest lists)
+  "Zip LISTS together.
+
+Group the head of each list, followed by the second element of
+each list, and so on.  The number of returned groupings is equal
+to the length of the shortest input list, and the number of items
+in each grouping is equal to the number of input LISTS.
+
+If only two LISTS are provided as arguments, return the groupings
+as a list of dotted pairs.  Otherwise, return the groupings as a
+list of proper lists.
+
+Since the return value changes form depending on the number of
+arguments, it is generally recommended to use `-zip-lists'
+instead, or `-zip-pair' if a list of dotted pairs is desired.
+
+See also: `-unzip'."
+  (declare (compiler-macro dash--zip-lists-or-pair)
+           (pure t) (side-effect-free t))
+  ;; For backward compatibility, return a list of dotted pairs if two
+  ;; arguments were provided.
+  (apply (if (dash--length= lists 2) #'-zip-pair #'-zip-lists) lists))
+
+(defun -zip-pair (&rest lists)
+  "Zip LIST1 and LIST2 together.
+
+Make a pair with the head of each list, followed by a pair with
+the second element of each list, and so on.  The number of pairs
+returned is equal to the length of the shorter input list.
+
+See also: `-zip-lists'."
+  (declare (advertised-calling-convention (list1 list2) "2.20.0")
+           (pure t) (side-effect-free t))
+  (if (dash--length= lists 2)
+      (--zip-with (cons it other) (car lists) (cadr lists))
+    (apply #'-zip-lists lists)))
+
+(defun -zip-fill (fill-value &rest lists)
+  "Zip LISTS together, padding shorter lists with FILL-VALUE.
+This is like `-zip' (which see), except it retains all elements
+at positions beyond the end of the shortest list.  The number of
+returned groupings is equal to the length of the longest input
+list, and the length of each grouping is equal to the number of
+input LISTS.
+
+Since the return value changes form depending on the number of
+arguments, it is generally recommended to use `-zip-lists-fill'
+instead, unless a list of dotted pairs is explicitly desired."
+  (declare (pure t) (side-effect-free t))
+  (cond ((null lists) ())
+        ((dash--length= lists 2)
+         (let ((list1 (car lists))
+               (list2 (cadr lists))
+               results)
+           (while (or list1 list2)
+             (push (cons (if list1 (pop list1) fill-value)
+                         (if list2 (pop list2) fill-value))
+                   results))
+           (nreverse results)))
+        ((apply #'-zip-lists-fill fill-value lists))))
+
+(defun -unzip (lists)
+  "Unzip LISTS.
+
+This works just like `-zip' (which see), but takes a list of
+lists instead of a variable number of arguments, such that
+
+  (-unzip (-zip L1 L2 L3 ...))
+
+is identity (given that the lists are of the same length, and
+that `-zip' is not called with two arguments, because of the
+caveat described in its docstring).
+
+Note in particular that calling `-unzip' on a list of two lists
+will return a list of dotted pairs.
+
+Since the return value changes form depending on the number of
+LISTS, it is generally recommended to use `-unzip-lists' instead."
+  (declare (pure t) (side-effect-free t))
+  (apply #'-zip lists))
+
+(defun -cycle (list)
+  "Return an infinite circular copy of LIST.
+The returned list cycles through the elements of LIST and repeats
+from the beginning."
+  (declare (pure t) (side-effect-free t))
+  ;; Also works with sequences that aren't lists.
+  (let ((newlist (append list ())))
+    (nconc newlist newlist)))
+
+(defun -pad (fill-value &rest lists)
+  "Pad each of LISTS with FILL-VALUE until they all have equal lengths.
+
+Ensure all LISTS are as long as the longest one by repeatedly
+appending FILL-VALUE to the shorter lists, and return the
+resulting LISTS."
+  (declare (pure t) (side-effect-free t))
+  (let* ((lens (mapcar #'length lists))
+         (maxlen (apply #'max 0 lens)))
+    (--map (append it (make-list (- maxlen (pop lens)) fill-value)) lists)))
+
+(defmacro --annotate (form list)
+  "Pair each item in LIST with the result of evaluating FORM.
+
+Return an alist of (RESULT . ITEM), where each ITEM is the
+corresponding element of LIST, and RESULT is the value obtained
+by evaluating FORM with ITEM bound to `it'.
+
+This is the anaphoric counterpart to `-annotate'."
+  (declare (debug (form form)))
+  `(--map (cons ,form it) ,list))
+
+(defun -annotate (fn list)
+  "Pair each item in LIST with the result of passing it to FN.
+
+Return an alist of (RESULT . ITEM), where each ITEM is the
+corresponding element of LIST, and RESULT is the value obtained
+by calling FN on ITEM.
+
+This function's anaphoric counterpart is `--annotate'."
+  (declare (important-return-value t))
+  (--annotate (funcall fn it) list))
+
+(defun dash--table-carry (lists restore-lists &optional re)
+  "Helper for `-table' and `-table-flat'.
+
+If a list overflows, carry to the right and reset the list."
+  (while (not (or (car lists)
+                  (equal lists '(nil))))
+    (setcar lists (car restore-lists))
+    (pop (cadr lists))
+    (!cdr lists)
+    (!cdr restore-lists)
+    (when re
+      (push (nreverse (car re)) (cadr re))
+      (setcar re nil)
+      (!cdr re))))
+
+(defun -table (fn &rest lists)
+  "Compute outer product of LISTS using function FN.
+
+The function FN should have the same arity as the number of
+supplied lists.
+
+The outer product is computed by applying fn to all possible
+combinations created by taking one element from each list in
+order.  The dimension of the result is (length lists).
+
+See also: `-table-flat'"
+  (declare (important-return-value t))
+  (let ((restore-lists (copy-sequence lists))
+        (last-list (last lists))
+        (re (make-list (length lists) nil)))
+    (while (car last-list)
+      (let ((item (apply fn (-map 'car lists))))
+        (push item (car re))
+        (setcar lists (cdar lists)) ;; silence byte compiler
+        (dash--table-carry lists restore-lists re)))
+    (nreverse (car (last re)))))
+
+(defun -table-flat (fn &rest lists)
+  "Compute flat outer product of LISTS using function FN.
+
+The function FN should have the same arity as the number of
+supplied lists.
+
+The outer product is computed by applying fn to all possible
+combinations created by taking one element from each list in
+order.  The results are flattened, ignoring the tensor structure
+of the result.  This is equivalent to calling:
+
+  (-flatten-n (1- (length lists)) (apply \\='-table fn lists))
+
+but the implementation here is much more efficient.
+
+See also: `-flatten-n', `-table'"
+  (declare (important-return-value t))
+  (let ((restore-lists (copy-sequence lists))
+        (last-list (last lists))
+        re)
+    (while (car last-list)
+      (let ((item (apply fn (-map 'car lists))))
+        (push item re)
+        (setcar lists (cdar lists)) ;; silence byte compiler
+        (dash--table-carry lists restore-lists)))
+    (nreverse re)))
+
+(defmacro --find-index (form list)
+  "Return the first index in LIST for which FORM evals to non-nil.
+Return nil if no such index is found.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-find-index'."
+  (declare (debug (form form)))
+  `(--some (and ,form it-index) ,list))
+
+(defun -find-index (pred list)
+  "Return the index of the first item satisfying PRED in LIST.
+Return nil if no such item is found.
+
+PRED is called with one argument, the current list element, until
+it returns non-nil, at which point the search terminates.
+
+This function's anaphoric counterpart is `--find-index'.
+
+See also: `-first', `-find-last-index'."
+  (declare (important-return-value t))
+  (--find-index (funcall pred it) list))
+
+(defun -elem-index (elem list)
+  "Return the first index of ELEM in LIST.
+That is, the index within LIST of the first element that is
+`equal' to ELEM.  Return nil if there is no such element.
+
+See also: `-find-index'."
+  (declare (pure t) (side-effect-free t))
+  (--find-index (equal elem it) list))
+
+(defmacro --find-indices (form list)
+  "Return the list of indices in LIST for which FORM evals to non-nil.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-find-indices'."
+  (declare (debug (form form)))
+  `(--keep (and ,form it-index) ,list))
+
+(defun -find-indices (pred list)
+  "Return the list of indices in LIST satisfying PRED.
+
+Each element of LIST in turn is passed to PRED.  If the result is
+non-nil, the index of that element in LIST is included in the
+result.  The returned indices are in ascending order, i.e., in
+the same order as they appear in LIST.
+
+This function's anaphoric counterpart is `--find-indices'.
+
+See also: `-find-index', `-elem-indices'."
+  (declare (important-return-value t))
+  (--find-indices (funcall pred it) list))
+
+(defun -elem-indices (elem list)
+  "Return the list of indices at which ELEM appears in LIST.
+That is, the indices of all elements of LIST `equal' to ELEM, in
+the same ascending order as they appear in LIST."
+  (declare (pure t) (side-effect-free t))
+  (--find-indices (equal elem it) list))
+
+(defmacro --find-last-index (form list)
+  "Return the last index in LIST for which FORM evals to non-nil.
+Return nil if no such index is found.
+Each element of LIST in turn is bound to `it' and its index
+within LIST to `it-index' before evaluating FORM.
+This is the anaphoric counterpart to `-find-last-index'."
+  (declare (debug (form form)))
+  (let ((i (make-symbol "index")))
+    `(let (,i)
+       (--each ,list
+         (when ,form (setq ,i it-index)))
+       ,i)))
+
+(defun -find-last-index (pred list)
+  "Return the index of the last item satisfying PRED in LIST.
+Return nil if no such item is found.
+
+Predicate PRED is called with one argument each time, namely the
+current list element.
+
+This function's anaphoric counterpart is `--find-last-index'.
+
+See also: `-last', `-find-index'."
+  (declare (important-return-value t))
+  (--find-last-index (funcall pred it) list))
+
+(defun -select-by-indices (indices list)
+  "Return a list whose elements are elements from LIST selected
+as `(nth i list)` for all i from INDICES."
+  (declare (pure t) (side-effect-free t))
+  (let (r)
+    (--each indices
+      (!cons (nth it list) r))
+    (nreverse r)))
+
+(defun -select-columns (columns table)
+  "Select COLUMNS from TABLE.
+
+TABLE is a list of lists where each element represents one row.
+It is assumed each row has the same length.
+
+Each row is transformed such that only the specified COLUMNS are
+selected.
+
+See also: `-select-column', `-select-by-indices'"
+  (declare (pure t) (side-effect-free t))
+  (--map (-select-by-indices columns it) table))
+
+(defun -select-column (column table)
+  "Select COLUMN from TABLE.
+
+TABLE is a list of lists where each element represents one row.
+It is assumed each row has the same length.
+
+The single selected column is returned as a list.
+
+See also: `-select-columns', `-select-by-indices'"
+  (declare (pure t) (side-effect-free t))
+  (--mapcat (-select-by-indices (list column) it) table))
+
+(defmacro -> (x &optional form &rest more)
+  "Thread the expr through the forms. Insert X as the second item
+in the first form, making a list of it if it is not a list
+already. If there are more forms, insert the first form as the
+second item in second form, etc."
+  (declare (debug (form &rest [&or symbolp (sexp &rest form)])))
+  (cond
+   ((null form) x)
+   ((null more) (if (listp form)
+                    `(,(car form) ,x ,@(cdr form))
+                  (list form x)))
+   (:else `(-> (-> ,x ,form) ,@more))))
+
+(defmacro ->> (x &optional form &rest more)
+  "Thread the expr through the forms. Insert X as the last item
+in the first form, making a list of it if it is not a list
+already. If there are more forms, insert the first form as the
+last item in second form, etc."
+  (declare (debug ->))
+  (cond
+   ((null form) x)
+   ((null more) (if (listp form)
+                    `(,@form ,x)
+                  (list form x)))
+   (:else `(->> (->> ,x ,form) ,@more))))
+
+(defmacro --> (x &rest forms)
+  "Starting with the value of X, thread each expression through FORMS.
+
+Insert X at the position signified by the symbol `it' in the first
+form.  If there are more forms, insert the first form at the position
+signified by `it' in the second form, etc."
+  (declare (debug (form body)))
+  `(-as-> ,x it ,@forms))
+
+(defmacro -as-> (value variable &rest forms)
+  "Starting with VALUE, thread VARIABLE through FORMS.
+
+In the first form, bind VARIABLE to VALUE.  In the second form, bind
+VARIABLE to the result of the first form, and so forth."
+  (declare (debug (form symbolp body)))
+  (if (null forms)
+      `,value
+    `(let ((,variable ,value))
+       (-as-> ,(if (symbolp (car forms))
+                   (list (car forms) variable)
+                 (car forms))
+              ,variable
+              ,@(cdr forms)))))
+
+(defmacro -some-> (x &optional form &rest more)
+  "When expr is non-nil, thread it through the first form (via `->'),
+and when that result is non-nil, through the next form, etc."
+  (declare (debug ->)
+           (indent 1))
+  (if (null form) x
+    (let ((result (make-symbol "result")))
+      `(-some-> (-when-let (,result ,x)
+                  (-> ,result ,form))
+         ,@more))))
+
+(defmacro -some->> (x &optional form &rest more)
+  "When expr is non-nil, thread it through the first form (via `->>'),
+and when that result is non-nil, through the next form, etc."
+  (declare (debug ->)
+           (indent 1))
+  (if (null form) x
+    (let ((result (make-symbol "result")))
+      `(-some->> (-when-let (,result ,x)
+                   (->> ,result ,form))
+         ,@more))))
+
+(defmacro -some--> (expr &rest forms)
+  "Thread EXPR through FORMS via `-->', while the result is non-nil.
+When EXPR evaluates to non-nil, thread the result through the
+first of FORMS, and when that result is non-nil, thread it
+through the next form, etc."
+  (declare (debug (form &rest &or symbolp consp)) (indent 1))
+  (if (null forms) expr
+    (let ((result (make-symbol "result")))
+      `(-some--> (-when-let (,result ,expr)
+                   (--> ,result ,(car forms)))
+         ,@(cdr forms)))))
+
+(defmacro -doto (init &rest forms)
+  "Evaluate INIT and pass it as argument to FORMS with `->'.
+The RESULT of evaluating INIT is threaded through each of FORMS
+individually using `->', which see.  The return value is RESULT,
+which FORMS may have modified by side effect."
+  (declare (debug (form &rest &or symbolp consp)) (indent 1))
+  (let ((retval (make-symbol "result")))
+    `(let ((,retval ,init))
+       ,@(mapcar (lambda (form) `(-> ,retval ,form)) forms)
+       ,retval)))
+
+(defmacro --doto (init &rest forms)
+  "Anaphoric form of `-doto'.
+This just evaluates INIT, binds the result to `it', evaluates
+FORMS, and returns the final value of `it'.
+Note: `it' need not be used in each form."
+  (declare (debug (form body)) (indent 1))
+  `(let ((it ,init))
+     ,@forms
+     it))
+
+(defun -grade-up (comparator list)
+  "Grade elements of LIST using COMPARATOR relation.
+This yields a permutation vector such that applying this
+permutation to LIST sorts it in ascending order."
+  (declare (important-return-value t))
+  (->> (--map-indexed (cons it it-index) list)
+       (-sort (lambda (it other) (funcall comparator (car it) (car other))))
+       (mapcar #'cdr)))
+
+(defun -grade-down (comparator list)
+  "Grade elements of LIST using COMPARATOR relation.
+This yields a permutation vector such that applying this
+permutation to LIST sorts it in descending order."
+  (declare (important-return-value t))
+  (->> (--map-indexed (cons it it-index) list)
+       (-sort (lambda (it other) (funcall comparator (car other) (car it))))
+       (mapcar #'cdr)))
+
+(defvar dash--source-counter 0
+  "Monotonic counter for generated symbols.")
+
+(defun dash--match-make-source-symbol ()
+  "Generate a new dash-source symbol.
+
+All returned symbols are guaranteed to be unique."
+  (prog1 (make-symbol (format "--dash-source-%d--" dash--source-counter))
+    (setq dash--source-counter (1+ dash--source-counter))))
+
+(defun dash--match-ignore-place-p (symbol)
+  "Return non-nil if SYMBOL is a symbol and starts with _."
+  (and (symbolp symbol)
+       (eq (aref (symbol-name symbol) 0) ?_)))
+
+(defun dash--match-cons-skip-cdr (skip-cdr source)
+  "Helper function generating idiomatic shifting code."
+  (cond
+   ((= skip-cdr 0)
+    `(pop ,source))
+   (t
+    `(prog1 ,(dash--match-cons-get-car skip-cdr source)
+       (setq ,source ,(dash--match-cons-get-cdr (1+ skip-cdr) source))))))
+
+(defun dash--match-cons-get-car (skip-cdr source)
+  "Helper function generating idiomatic code to get nth car."
+  (cond
+   ((= skip-cdr 0)
+    `(car ,source))
+   ((= skip-cdr 1)
+    `(cadr ,source))
+   (t
+    `(nth ,skip-cdr ,source))))
+
+(defun dash--match-cons-get-cdr (skip-cdr source)
+  "Helper function generating idiomatic code to get nth cdr."
+  (cond
+   ((= skip-cdr 0)
+    source)
+   ((= skip-cdr 1)
+    `(cdr ,source))
+   (t
+    `(nthcdr ,skip-cdr ,source))))
+
+(defun dash--match-cons (match-form source)
+  "Setup a cons matching environment and call the real matcher."
+  (let ((s (dash--match-make-source-symbol))
+        (n 0)
+        (m match-form))
+    (while (and (consp m)
+                (dash--match-ignore-place-p (car m)))
+      (setq n (1+ n)) (!cdr m))
+    (cond
+     ;; when we only have one pattern in the list, we don't have to
+     ;; create a temporary binding (--dash-source--) for the source
+     ;; and just use the input directly
+     ((and (consp m)
+           (not (cdr m)))
+      (dash--match (car m) (dash--match-cons-get-car n source)))
+     ;; handle other special types
+     ((> n 0)
+      (dash--match m (dash--match-cons-get-cdr n source)))
+     ;; this is the only entry-point for dash--match-cons-1, that's
+     ;; why we can't simply use the above branch, it would produce
+     ;; infinite recursion
+     (t
+      (cons (list s source) (dash--match-cons-1 match-form s))))))
+
+(defun dash--get-expand-function (type)
+  "Get expand function name for TYPE."
+  (intern-soft (format "dash-expand:%s" type)))
+
+(defun dash--match-cons-1 (match-form source &optional props)
+  "Match MATCH-FORM against SOURCE.
+
+MATCH-FORM is a proper or improper list.  Each element of
+MATCH-FORM is either a symbol, which gets bound to the respective
+value in source or another match form which gets destructured
+recursively.
+
+If the cdr of last cons cell in the list is nil, matching stops
+there.
+
+SOURCE is a proper or improper list."
+  (let ((skip-cdr (or (plist-get props :skip-cdr) 0)))
+    (cond
+     ((consp match-form)
+      (cond
+       ((cdr match-form)
+        (cond
+         ((and (symbolp (car match-form))
+               (functionp (dash--get-expand-function (car match-form))))
+          (dash--match-kv (dash--match-kv-normalize-match-form match-form) (dash--match-cons-get-cdr skip-cdr source)))
+         ((dash--match-ignore-place-p (car match-form))
+          (dash--match-cons-1 (cdr match-form) source
+                              (plist-put props :skip-cdr (1+ skip-cdr))))
+         (t
+          (-concat (dash--match (car match-form) (dash--match-cons-skip-cdr skip-cdr source))
+                   (dash--match-cons-1 (cdr match-form) source)))))
+       (t ;; Last matching place, no need for shift
+        (dash--match (car match-form) (dash--match-cons-get-car skip-cdr source)))))
+     ((eq match-form nil)
+      nil)
+     (t ;; Handle improper lists.  Last matching place, no need for shift
+      (dash--match match-form (dash--match-cons-get-cdr skip-cdr source))))))
+
+(defun dash--match-vector (match-form source)
+  "Setup a vector matching environment and call the real matcher."
+  (let ((s (dash--match-make-source-symbol)))
+    (cond
+     ;; don't bind `s' if we only have one sub-pattern
+     ((= (length match-form) 1)
+      (dash--match (aref match-form 0) `(aref ,source 0)))
+     ;; if the source is a symbol, we don't need to re-bind it
+     ((symbolp source)
+      (dash--match-vector-1 match-form source))
+     ;; don't bind `s' if we only have one sub-pattern which is not ignored
+     ((let* ((ignored-places (mapcar 'dash--match-ignore-place-p match-form))
+             (ignored-places-n (length (-remove 'null ignored-places))))
+        (when (= ignored-places-n (1- (length match-form)))
+          (let ((n (-find-index 'null ignored-places)))
+            (dash--match (aref match-form n) `(aref ,source ,n))))))
+     (t
+      (cons (list s source) (dash--match-vector-1 match-form s))))))
+
+(defun dash--match-vector-1 (match-form source)
+  "Match MATCH-FORM against SOURCE.
+
+MATCH-FORM is a vector.  Each element of MATCH-FORM is either a
+symbol, which gets bound to the respective value in source or
+another match form which gets destructured recursively.
+
+If second-from-last place in MATCH-FORM is the symbol &rest, the
+next element of the MATCH-FORM is matched against the tail of
+SOURCE, starting at index of the &rest symbol.  This is
+conceptually the same as the (head . tail) match for improper
+lists, where dot plays the role of &rest.
+
+SOURCE is a vector.
+
+If the MATCH-FORM vector is shorter than SOURCE vector, only
+the (length MATCH-FORM) places are bound, the rest of the SOURCE
+is discarded."
+  (let ((i 0)
+        (l (length match-form))
+        (re))
+    (while (< i l)
+      (let ((m (aref match-form i)))
+        (push (cond
+               ((and (symbolp m)
+                     (eq m '&rest))
+                (prog1 (dash--match
+                        (aref match-form (1+ i))
+                        `(substring ,source ,i))
+                  (setq i l)))
+               ((and (symbolp m)
+                     ;; do not match symbols starting with _
+                     (not (eq (aref (symbol-name m) 0) ?_)))
+                (list (list m `(aref ,source ,i))))
+               ((not (symbolp m))
+                (dash--match m `(aref ,source ,i))))
+              re)
+        (setq i (1+ i))))
+    (-flatten-n 1 (nreverse re))))
+
+(defun dash--match-kv-normalize-match-form (pattern)
+  "Normalize kv PATTERN.
+
+This method normalizes PATTERN to the format expected by
+`dash--match-kv'.  See `-let' for the specification."
+  (let ((normalized (list (car pattern)))
+        (skip nil)
+        (fill-placeholder (make-symbol "--dash-fill-placeholder--")))
+    (-each (-zip-fill fill-placeholder (cdr pattern) (cddr pattern))
+      (lambda (pair)
+        (let ((current (car pair))
+              (next (cdr pair)))
+          (if skip
+              (setq skip nil)
+            (if (or (eq fill-placeholder next)
+                    (not (or (and (symbolp next)
+                                  (not (keywordp next))
+                                  (not (eq next t))
+                                  (not (eq next nil)))
+                             (and (consp next)
+                                  (not (eq (car next) 'quote)))
+                             (vectorp next))))
+                (progn
+                  (cond
+                   ((keywordp current)
+                    (push current normalized)
+                    (push (intern (substring (symbol-name current) 1)) normalized))
+                   ((stringp current)
+                    (push current normalized)
+                    (push (intern current) normalized))
+                   ((and (consp current)
+                         (eq (car current) 'quote))
+                    (push current normalized)
+                    (push (cadr current) normalized))
+                   (t (error "-let: found key `%s' in kv destructuring but its pattern `%s' is invalid and can not be derived from the key" current next)))
+                  (setq skip nil))
+              (push current normalized)
+              (push next normalized)
+              (setq skip t))))))
+    (nreverse normalized)))
+
+(defun dash--match-kv (match-form source)
+  "Setup a kv matching environment and call the real matcher.
+
+kv can be any key-value store, such as plist, alist or hash-table."
+  (let ((s (dash--match-make-source-symbol)))
+    (cond
+     ;; don't bind `s' if we only have one sub-pattern (&type key val)
+     ((= (length match-form) 3)
+      (dash--match-kv-1 (cdr match-form) source (car match-form)))
+     ;; if the source is a symbol, we don't need to re-bind it
+     ((symbolp source)
+      (dash--match-kv-1 (cdr match-form) source (car match-form)))
+     (t
+      (cons (list s source) (dash--match-kv-1 (cdr match-form) s (car match-form)))))))
+
+(defun dash-expand:&hash (key source)
+  "Generate extracting KEY from SOURCE for &hash destructuring."
+  `(gethash ,key ,source))
+
+(defun dash-expand:&plist (key source)
+  "Generate extracting KEY from SOURCE for &plist destructuring."
+  `(plist-get ,source ,key))
+
+(defun dash-expand:&alist (key source)
+  "Generate extracting KEY from SOURCE for &alist destructuring."
+  `(cdr (assoc ,key ,source)))
+
+(defun dash-expand:&hash? (key source)
+  "Generate extracting KEY from SOURCE for &hash? destructuring.
+Similar to &hash but check whether the map is not nil."
+  (let ((src (make-symbol "src")))
+    `(let ((,src ,source))
+       (when ,src (gethash ,key ,src)))))
+
+(defalias 'dash-expand:&keys #'dash-expand:&plist)
+
+(defun dash--match-kv-1 (match-form source type)
+  "Match MATCH-FORM against SOURCE of type TYPE.
+
+MATCH-FORM is a proper list of the form (key1 place1 ... keyN
+placeN).  Each placeK is either a symbol, which gets bound to the
+value of keyK retrieved from the key-value store, or another
+match form which gets destructured recursively.
+
+SOURCE is a key-value store of type TYPE, which can be a plist,
+an alist or a hash table.
+
+TYPE is a token specifying the type of the key-value store.
+Valid values are &plist, &alist and &hash."
+  (-flatten-n 1 (-map
+                 (lambda (kv)
+                   (let* ((k (car kv))
+                          (v (cadr kv))
+                          (getter
+                           (funcall (dash--get-expand-function type) k source)))
+                     (cond
+                      ((symbolp v)
+                       (list (list v getter)))
+                      (t (dash--match v getter)))))
+                 (-partition 2 match-form))))
+
+(defun dash--match-symbol (match-form source)
+  "Bind a symbol.
+
+This works just like `let', there is no destructuring."
+  (list (list match-form source)))
+
+(defun dash--match (match-form source)
+  "Match MATCH-FORM against SOURCE.
+
+This function tests the MATCH-FORM and dispatches to specific
+matchers based on the type of the expression.
+
+Key-value stores are disambiguated by placing a token &plist,
+&alist or &hash as a first item in the MATCH-FORM."
+  (cond
+   ((and (symbolp match-form)
+         ;; Don't bind things like &keys as if they were vars (#395).
+         (not (functionp (dash--get-expand-function match-form))))
+    (dash--match-symbol match-form source))
+   ((consp match-form)
+    (cond
+     ;; Handle the "x &as" bindings first.
+     ((and (consp (cdr match-form))
+           (symbolp (car match-form))
+           (eq '&as (cadr match-form)))
+      (let ((s (car match-form)))
+        (cons (list s source)
+              (dash--match (cddr match-form) s))))
+     ((functionp (dash--get-expand-function (car match-form)))
+      (dash--match-kv (dash--match-kv-normalize-match-form match-form) source))
+     (t (dash--match-cons match-form source))))
+   ((vectorp match-form)
+    ;; We support the &as binding in vectors too
+    (cond
+     ((and (> (length match-form) 2)
+           (symbolp (aref match-form 0))
+           (eq '&as (aref match-form 1)))
+      (let ((s (aref match-form 0)))
+        (cons (list s source)
+              (dash--match (substring match-form 2) s))))
+     (t (dash--match-vector match-form source))))))
+
+(defun dash--normalize-let-varlist (varlist)
+  "Normalize VARLIST so that every binding is a list.
+
+`let' allows specifying a binding which is not a list but simply
+the place which is then automatically bound to nil, such that all
+three of the following are identical and evaluate to nil.
+
+  (let (a) a)
+  (let ((a)) a)
+  (let ((a nil)) a)
+
+This function normalizes all of these to the last form."
+  (--map (if (consp it) it (list it nil)) varlist))
+
+(defmacro -let* (varlist &rest body)
+  "Bind variables according to VARLIST then eval BODY.
+
+VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
+PATTERN is matched against the SOURCE structurally.  SOURCE is
+only evaluated once for each PATTERN.
+
+Each SOURCE can refer to the symbols already bound by this
+VARLIST.  This is useful if you want to destructure SOURCE
+recursively but also want to name the intermediate structures.
+
+See `-let' for the list of all possible patterns."
+  (declare (debug ((&rest [&or (sexp form) sexp]) body))
+           (indent 1))
+  (let* ((varlist (dash--normalize-let-varlist varlist))
+         (bindings (--mapcat (dash--match (car it) (cadr it)) varlist)))
+    `(let* ,bindings
+       ,@body)))
+
+(defmacro -let (varlist &rest body)
+  "Bind variables according to VARLIST then eval BODY.
+
+VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
+PATTERN is matched against the SOURCE \"structurally\".  SOURCE
+is only evaluated once for each PATTERN.  Each PATTERN is matched
+recursively, and can therefore contain sub-patterns which are
+matched against corresponding sub-expressions of SOURCE.
+
+All the SOURCEs are evalled before any symbols are
+bound (i.e. \"in parallel\").
+
+If VARLIST only contains one (PATTERN SOURCE) element, you can
+optionally specify it using a vector and discarding the
+outer-most parens.  Thus
+
+  (-let ((PATTERN SOURCE)) ...)
+
+becomes
+
+  (-let [PATTERN SOURCE] ...).
+
+`-let' uses a convention of not binding places (symbols) starting
+with _ whenever it's possible.  You can use this to skip over
+entries you don't care about.  However, this is not *always*
+possible (as a result of implementation) and these symbols might
+get bound to undefined values.
+
+Following is the overview of supported patterns.  Remember that
+patterns can be matched recursively, so every a, b, aK in the
+following can be a matching construct and not necessarily a
+symbol/variable.
+
+Symbol:
+
+  a - bind the SOURCE to A.  This is just like regular `let'.
+
+Conses and lists:
+
+  (a) - bind `car' of cons/list to A
+
+  (a . b) - bind car of cons to A and `cdr' to B
+
+  (a b) - bind car of list to A and `cadr' to B
+
+  (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3...
+
+  (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST.
+
+Vectors:
+
+  [a] - bind 0th element of a non-list sequence to A (works with
+        vectors, strings, bit arrays...)
+
+  [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st to
+                   A1, 2nd to A2, ...
+                   If the PATTERN is shorter than SOURCE, the values at
+                   places not in PATTERN are ignored.
+                   If the PATTERN is longer than SOURCE, an `error' is
+                   thrown.
+
+  [a1 a2 a3 ... &rest rest] - as above, but bind the rest of
+                              the sequence to REST.  This is
+                              conceptually the same as improper list
+                              matching (a1 a2 ... aN . rest)
+
+Key/value stores:
+
+  (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+                                 SOURCE plist to aK.  If the
+                                 value is not found, aK is nil.
+                                 Uses `plist-get' to fetch values.
+
+  (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+                                 SOURCE alist to aK.  If the
+                                 value is not found, aK is nil.
+                                 Uses `assoc' to fetch values.
+
+  (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the
+                                SOURCE hash table to aK.  If the
+                                value is not found, aK is nil.
+                                Uses `gethash' to fetch values.
+
+Further, special keyword &keys supports \"inline\" matching of
+plist-like key-value pairs, similarly to &keys keyword of
+`cl-defun'.
+
+  (a1 a2 ... aN &keys key1 b1 ... keyN bK)
+
+This binds N values from the list to a1 ... aN, then interprets
+the cdr as a plist (see key/value matching above).
+
+A shorthand notation for kv-destructuring exists which allows the
+patterns be optionally left out and derived from the key name in
+the following fashion:
+
+- a key :foo is converted into `foo' pattern,
+- a key \\='bar is converted into `bar' pattern,
+- a key \"baz\" is converted into `baz' pattern.
+
+That is, the entire value under the key is bound to the derived
+variable without any further destructuring.
+
+This is possible only when the form following the key is not a
+valid pattern (i.e. not a symbol, a cons cell or a vector).
+Otherwise the matching proceeds as usual and in case of an
+invalid spec fails with an error.
+
+Thus the patterns are normalized as follows:
+
+   ;; derive all the missing patterns
+   (&plist :foo \\='bar \"baz\") => (&plist :foo foo \\='bar bar \"baz\" baz)
+
+   ;; we can specify some but not others
+   (&plist :foo \\='bar explicit-bar) => (&plist :foo foo \\='bar explicit-bar)
+
+   ;; nothing happens, we store :foo in x
+   (&plist :foo x) => (&plist :foo x)
+
+   ;; nothing happens, we match recursively
+   (&plist :foo (a b c)) => (&plist :foo (a b c))
+
+You can name the source using the syntax SYMBOL &as PATTERN.
+This syntax works with lists (proper or improper), vectors and
+all types of maps.
+
+  (list &as a b c) (list 1 2 3)
+
+binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
+
+Similarly:
+
+  (bounds &as beg . end) (cons 1 2)
+
+binds BEG to 1, END to 2 and BOUNDS to (1 . 2).
+
+  (items &as first . rest) (list 1 2 3)
+
+binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
+
+  [vect &as _ b c] [1 2 3]
+
+binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as usual).
+
+  (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+binds B to 2 and PLIST to (:a 1 :b 2 :c 3).  Same for &alist and &hash.
+
+This is especially useful when we want to capture the result of a
+computation and destructure at the same time.  Consider the
+form (function-returning-complex-structure) returning a list of
+two vectors with two items each.  We want to capture this entire
+result and pass it to another computation, but at the same time
+we want to get the second item from each vector.  We can achieve
+it with pattern
+
+  (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+Note: Clojure programmers may know this feature as the \":as
+binding\".  The difference is that we put the &as at the front
+because we need to support improper list binding."
+  (declare (debug ([&or (&rest [&or (sexp form) sexp])
+                        (vector [&rest [sexp form]])]
+                   body))
+           (indent 1))
+  (if (vectorp varlist)
+      `(let* ,(dash--match (aref varlist 0) (aref varlist 1))
+         ,@body)
+    (let* ((varlist (dash--normalize-let-varlist varlist))
+           (inputs (--map-indexed (list (make-symbol (format "input%d" it-index)) (cadr it)) varlist))
+           (new-varlist (--zip-with (list (car it) (car other))
+                                    varlist inputs)))
+      `(let ,inputs
+         (-let* ,new-varlist ,@body)))))
+
+(defmacro -lambda (match-form &rest body)
+  "Return a lambda which destructures its input as MATCH-FORM and executes BODY.
+
+Note that you have to enclose the MATCH-FORM in a pair of parens,
+such that:
+
+  (-lambda (x) body)
+  (-lambda (x y ...) body)
+
+has the usual semantics of `lambda'.  Furthermore, these get
+translated into normal `lambda', so there is no performance
+penalty.
+
+See `-let' for a description of the destructuring mechanism."
+  (declare (doc-string 2) (indent defun)
+           (debug (&define sexp
+                           [&optional stringp]
+                           [&optional ("interactive" interactive)]
+                           def-body)))
+  (cond
+   ((nlistp match-form)
+    (signal 'wrong-type-argument (list #'listp match-form)))
+   ;; No destructuring, so just return regular `lambda' for speed.
+   ((-all? #'symbolp match-form)
+    `(lambda ,match-form ,@body))
+   ((let ((inputs (--map-indexed
+                   (list it (make-symbol (format "input%d" it-index)))
+                   match-form)))
+      ;; TODO: because inputs to the `lambda' are evaluated only once,
+      ;; `-let*' need not create the extra bindings to ensure that.
+      ;; We should find a way to optimize that.  Not critical however.
+      `(lambda ,(mapcar #'cadr inputs)
+         (-let* ,inputs ,@body))))))
+
+(defmacro -setq (&rest forms)
+  "Bind each MATCH-FORM to the value of its VAL.
+
+MATCH-FORM destructuring is done according to the rules of `-let'.
+
+This macro allows you to bind multiple variables by destructuring
+the value, so for example:
+
+  (-setq (a b) x
+         (&plist :c c) plist)
+
+expands roughly speaking to the following code
+
+  (setq a (car x)
+        b (cadr x)
+        c (plist-get plist :c))
+
+Care is taken to only evaluate each VAL once so that in case of
+multiple assignments it does not cause unexpected side effects.
+
+\(fn [MATCH-FORM VAL]...)"
+  (declare (debug (&rest sexp form))
+           (indent 1))
+  (when (= (mod (length forms) 2) 1)
+    (signal 'wrong-number-of-arguments (list '-setq (1+ (length forms)))))
+  (let* ((forms-and-sources
+          ;; First get all the necessary mappings with all the
+          ;; intermediate bindings.
+          (-map (lambda (x) (dash--match (car x) (cadr x)))
+                (-partition 2 forms)))
+         ;; To preserve the logic of dynamic scoping we must ensure
+         ;; that we `setq' the variables outside of the `let*' form
+         ;; which holds the destructured intermediate values.  For
+         ;; this we generate for each variable a placeholder which is
+         ;; bound to (lexically) the result of the destructuring.
+         ;; Then outside of the helper `let*' form we bind all the
+         ;; original variables to their respective placeholders.
+         ;; TODO: There is a lot of room for possible optimization,
+         ;; for start playing with `special-variable-p' to eliminate
+         ;; unnecessary re-binding.
+         (variables-to-placeholders
+          (-mapcat
+           (lambda (bindings)
+             (-map
+              (lambda (binding)
+                (let ((var (car binding)))
+                  (list var (make-symbol (concat "--dash-binding-" (symbol-name var) "--")))))
+              (--filter (not (string-prefix-p "--" (symbol-name (car it)))) bindings)))
+           forms-and-sources)))
+    `(let ,(-map 'cadr variables-to-placeholders)
+       (let* ,(-flatten-n 1 forms-and-sources)
+         (setq ,@(-flatten (-map 'reverse variables-to-placeholders))))
+       (setq ,@(-flatten variables-to-placeholders)))))
+
+(defmacro -if-let* (vars-vals then &rest else)
+  "If all VALS evaluate to true, bind them to their corresponding
+VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list
+of (VAR VAL) pairs.
+
+Note: binding is done according to `-let*'.  VALS are evaluated
+sequentially, and evaluation stops after the first nil VAL is
+encountered."
+  (declare (debug ((&rest (sexp form)) form body))
+           (indent 2))
+  (->> vars-vals
+       (--mapcat (dash--match (car it) (cadr it)))
+       (--reduce-r-from
+        (let ((var (car it))
+              (val (cadr it)))
+          `(let ((,var ,val))
+             (if ,var ,acc ,@else)))
+        then)))
+
+(defmacro -if-let (var-val then &rest else)
+  "If VAL evaluates to non-nil, bind it to VAR and do THEN,
+otherwise do ELSE.
+
+Note: binding is done according to `-let'.
+
+\(fn (VAR VAL) THEN &rest ELSE)"
+  (declare (debug ((sexp form) form body))
+           (indent 2))
+  `(-if-let* (,var-val) ,then ,@else))
+
+(defmacro --if-let (val then &rest else)
+  "If VAL evaluates to non-nil, bind it to symbol `it' and do THEN,
+otherwise do ELSE."
+  (declare (debug (form form body))
+           (indent 2))
+  `(-if-let (it ,val) ,then ,@else))
+
+(defmacro -when-let* (vars-vals &rest body)
+  "If all VALS evaluate to true, bind them to their corresponding
+VARS and execute body. VARS-VALS should be a list of (VAR VAL)
+pairs.
+
+Note: binding is done according to `-let*'.  VALS are evaluated
+sequentially, and evaluation stops after the first nil VAL is
+encountered."
+  (declare (debug ((&rest (sexp form)) body))
+           (indent 1))
+  `(-if-let* ,vars-vals (progn ,@body)))
+
+(defmacro -when-let (var-val &rest body)
+  "If VAL evaluates to non-nil, bind it to VAR and execute body.
+
+Note: binding is done according to `-let'.
+
+\(fn (VAR VAL) &rest BODY)"
+  (declare (debug ((sexp form) body))
+           (indent 1))
+  `(-if-let ,var-val (progn ,@body)))
+
+(defmacro --when-let (val &rest body)
+  "If VAL evaluates to non-nil, bind it to symbol `it' and
+execute body."
+  (declare (debug (form body))
+           (indent 1))
+  `(--if-let ,val (progn ,@body)))
+
+;; TODO: Get rid of this dynamic variable, passing it as an argument
+;; instead?
+(defvar -compare-fn nil
+  "Tests for equality use this function, or `equal' if this is nil.
+
+As a dynamic variable, this should be temporarily bound around
+the relevant operation, rather than permanently modified.  For
+example:
+
+  (let ((-compare-fn #\\='=))
+    (-union \\='(1 2 3) \\='(2 3 4)))")
+
+(defun dash--member-fn ()
+  "Return the flavor of `member' that goes best with `-compare-fn'."
+  (declare (side-effect-free error-free))
+  (let ((cmp -compare-fn))
+    (cond ((memq cmp '(nil equal)) #'member)
+          ((eq cmp #'eq) #'memq)
+          ((eq cmp #'eql) #'memql)
+          ((lambda (elt list)
+             (while (and list (not (funcall cmp elt (car list))))
+               (pop list))
+             list)))))
+
+(defun dash--assoc-fn ()
+  "Return the flavor of `assoc' that goes best with `-compare-fn'."
+  (declare (side-effect-free error-free))
+  (let ((cmp -compare-fn))
+    (cond ((memq cmp '(nil equal)) #'assoc)
+          ((eq cmp #'eq) #'assq)
+          ((lambda (key alist)
+             ;; Since Emacs 26, `assoc' accepts a custom `testfn'.
+             ;; Version testing would be simpler here, but feature
+             ;; testing gets more brownie points, I guess.
+             (static-if (condition-case nil
+                            (assoc nil () #'eql)
+                          (wrong-number-of-arguments t))
+                 (--first (and (consp it) (funcall cmp (car it) key)) alist)
+               (assoc key alist cmp)))))))
+
+(defun dash--hash-test-fn ()
+  "Return the hash table test function corresponding to `-compare-fn'.
+Return nil if `-compare-fn' is not a known test function."
+  (declare (side-effect-free error-free))
+  ;; In theory this could also recognize values that are custom
+  ;; `hash-table-test's, but too often the :test name is different
+  ;; from the equality function, so it doesn't seem worthwhile.
+  (car (memq (or -compare-fn #'equal) '(equal eq eql))))
+
+(defvar dash--short-list-length 32
+  "Maximum list length considered short, for optimizations.
+For example, the speedup afforded by hash table lookup may start
+to outweigh its runtime and memory overhead for problem sizes
+greater than this value.  See also the discussion in PR #305.")
+
+(defun -distinct (list)
+  "Return a copy of LIST with all duplicate elements removed.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that is non-nil.
+
+Alias: `-uniq'."
+  (declare (important-return-value t))
+  (let (test len)
+    (cond ((null list) ())
+          ;; Use a hash table if `-compare-fn' is a known hash table
+          ;; test function and the list is long enough.
+          ((and (setq test (dash--hash-test-fn))
+                (> (setq len (length list)) dash--short-list-length))
+           (let ((ht (make-hash-table :test test :size len)))
+             (--filter (unless (gethash it ht) (puthash it t ht)) list)))
+          ((let ((member (dash--member-fn)) uniq)
+             (--each list (unless (funcall member it uniq) (push it uniq)))
+             (nreverse uniq))))))
+
+(defalias '-uniq #'-distinct)
+
+(defun dash--size+ (size1 size2)
+  "Return the sum of nonnegative fixnums SIZE1 and SIZE2.
+Return `most-positive-fixnum' on overflow.  This ensures the
+result is a valid size, particularly for allocating hash tables,
+even in the presence of bignum support."
+  (declare (side-effect-free t))
+  (if (< size1 (- most-positive-fixnum size2))
+      (+ size1 size2)
+    most-positive-fixnum))
+
+(defun -union (list1 list2)
+  "Return a new list of distinct elements appearing in either LIST1 or LIST2.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that is non-nil."
+  (declare (important-return-value t))
+  (let ((lists (list list1 list2)) test len union)
+    (cond ((null (or list1 list2)))
+          ;; Use a hash table if `-compare-fn' is a known hash table
+          ;; test function and the lists are long enough.
+          ((and (setq test (dash--hash-test-fn))
+                (> (setq len (dash--size+ (length list1) (length list2)))
+                   dash--short-list-length))
+           (let ((ht (make-hash-table :test test :size len)))
+             (dolist (l lists)
+               (--each l (unless (gethash it ht)
+                           (puthash it t ht)
+                           (push it union))))))
+          ((let ((member (dash--member-fn)))
+             (dolist (l lists)
+               (--each l (unless (funcall member it union) (push it union)))))))
+    (nreverse union)))
+
+(defun -intersection (list1 list2)
+  "Return a new list of distinct elements appearing in both LIST1 and LIST2.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that is non-nil."
+  (declare (important-return-value t))
+  (let (test len)
+    (cond ((null (and list1 list2)) ())
+          ;; Use a hash table if `-compare-fn' is a known hash table
+          ;; test function and either list is long enough.
+          ((and (setq test (dash--hash-test-fn))
+                (> (setq len (length list2)) dash--short-list-length))
+           (let ((ht (make-hash-table :test test :size len)))
+             (--each list2 (puthash it t ht))
+             ;; Remove visited elements to avoid duplicates.
+             (--filter (when (gethash it ht) (remhash it ht) t) list1)))
+          ((let ((member (dash--member-fn)) intersection)
+             (--each list1 (and (funcall member it list2)
+                                (not (funcall member it intersection))
+                                (push it intersection)))
+             (nreverse intersection))))))
+
+(defun -difference (list1 list2)
+  "Return a new list with the distinct members of LIST1 that are not in LIST2.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that is non-nil."
+  (declare (important-return-value t))
+  (let (test len1 len2)
+    (cond ((null list1) ())
+          ((null list2) (-distinct list1))
+          ;; Use a hash table if `-compare-fn' is a known hash table
+          ;; test function and the subtrahend is long enough.
+          ((and (setq test (dash--hash-test-fn))
+                (setq len1 (length list1))
+                (setq len2 (length list2))
+                (> (max len1 len2) dash--short-list-length))
+           (let ((ht1 (make-hash-table :test test :size len1))
+                 (ht2 (make-hash-table :test test :size len2)))
+             (--each list2 (puthash it t ht2))
+             ;; Avoid duplicates by tracking visited items in `ht1'.
+             (--filter (unless (or (gethash it ht2) (gethash it ht1))
+                         (puthash it t ht1))
+                       list1)))
+          ((let ((member (dash--member-fn)) difference)
+             (--each list1
+               (unless (or (funcall member it list2)
+                           (funcall member it difference))
+                 (push it difference)))
+             (nreverse difference))))))
+
+(defun -powerset (list)
+  "Return the power set of LIST."
+  (declare (pure t) (side-effect-free t))
+  (if (null list) (list ())
+    (let ((last (-powerset (cdr list))))
+      (nconc (mapcar (lambda (x) (cons (car list) x)) last)
+             last))))
+
+(defun -frequencies (list)
+  "Count the occurrences of each distinct element of LIST.
+
+Return an alist of (ELEMENT . N), where each ELEMENT occurs N
+times in LIST.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that is non-nil.
+
+See also `-count' and `-group-by'."
+  (declare (important-return-value t))
+  (let (test len freqs)
+    (cond ((null list))
+          ((and (setq test (dash--hash-test-fn))
+                (> (setq len (length list)) dash--short-list-length))
+           (let ((ht (make-hash-table :test test :size len)))
+             ;; Share structure between hash table and returned list.
+             ;; This affords a single pass that preserves the input
+             ;; order, conses less garbage, and is faster than a
+             ;; second traversal (e.g., with `maphash').
+             (--each list
+               (let ((freq (gethash it ht)))
+                 (if freq
+                     (setcdr freq (1+ (cdr freq)))
+                   (push (puthash it (cons it 1) ht) freqs))))))
+          ((let ((assoc (dash--assoc-fn)))
+             (--each list
+               (let ((freq (funcall assoc it freqs)))
+                 (if freq
+                     (setcdr freq (1+ (cdr freq)))
+                   (push (cons it 1) freqs)))))))
+    (nreverse freqs)))
+
+(defun dash--numbers<= (nums)
+  "Return non-nil if NUMS is a list of non-decreasing numbers."
+  (declare (pure t) (side-effect-free t))
+  (or (null nums)
+      (let ((prev (pop nums)))
+        (and (numberp prev)
+             (--every (and (numberp it) (<= prev (setq prev it))) nums)))))
+
+(defun dash--next-lex-perm (array n)
+  "Update ARRAY of N numbers with its next lexicographic permutation.
+Return nil if there is no such successor.  N should be nonzero.
+
+This implements the salient steps of Algorithm L (Lexicographic
+permutation generation) as described in DE Knuth's The Art of
+Computer Programming, Volume 4A / Combinatorial Algorithms,
+Part I, Addison-Wesley, 2011, § 7.2.1.2, p. 319."
+  (setq n (1- n))
+  (let* ((l n)
+         (j (1- n))
+         (al (aref array n))
+         (aj al))
+    ;; L2. [Find j].
+    ;; Decrement j until a[j] < a[j+1].
+    (while (and (<= 0 j)
+                (<= aj (setq aj (aref array j))))
+      (setq j (1- j)))
+    ;; Terminate algorithm if j not found.
+    (when (>= j 0)
+      ;; L3. [Increase a[j]].
+      ;; Decrement l until a[j] < a[l].
+      (while (>= aj al)
+        (setq l (1- l) al (aref array l)))
+      ;; Swap a[j] and a[l].
+      (aset array j al)
+      (aset array l aj)
+      ;; L4. [Reverse a[j+1]...a[n]].
+      (setq l n)
+      (while (< (setq j (1+ j)) l)
+        (setq aj (aref array j))
+        (aset array j (aref array l))
+        (aset array l aj)
+        (setq l (1- l)))
+      array)))
+
+(defun dash--lex-perms (vec &optional original)
+  "Return a list of permutations of VEC in lexicographic order.
+Specifically, return only the successors of VEC in lexicographic
+order.  Each returned permutation is a list.  VEC should comprise
+one or more numbers, and may be destructively modified.
+
+If ORIGINAL is a vector, then VEC is interpreted as a set of
+indices into ORIGINAL.  In this case, the indices are permuted,
+and the resulting index permutations are used to dereference
+elements of ORIGINAL."
+  (let ((len (length vec)) perms)
+    (while vec
+      (push (if original
+                (--map (aref original it) vec)
+              (append vec ()))
+            perms)
+      (setq vec (dash--next-lex-perm vec len)))
+    (nreverse perms)))
+
+(defun dash--uniq-perms (list)
+  "Return a list of permutations of LIST.
+LIST is treated as if all its elements are distinct."
+  (let* ((vec (vconcat list))
+         (idxs (copy-sequence vec)))
+    ;; Just construct a vector of the list's indices and permute that.
+    (dotimes (i (length idxs))
+      (aset idxs i i))
+    (dash--lex-perms idxs vec)))
+
+(defun dash--multi-perms (list freqs)
+  "Return a list of permutations of the multiset LIST.
+FREQS should be an alist describing the frequency of each element
+in LIST, as returned by `-frequencies'."
+  (let (;; Distinct items in `list', aka the cars of `freqs'.
+        (uniq (make-vector (length freqs) nil))
+        ;; Indices into `uniq'.
+        (idxs (make-vector (length list) nil))
+        ;; Current index into `idxs'.
+        (i 0))
+    (--each freqs
+      (aset uniq it-index (car it))
+      ;; Populate `idxs' with as many copies of each `it-index' as
+      ;; there are corresponding duplicates.
+      (dotimes (_ (cdr it))
+        (aset idxs i it-index)
+        (setq i (1+ i))))
+    (dash--lex-perms idxs uniq)))
+
+(defun -permutations (list)
+  "Return the distinct permutations of LIST.
+
+Duplicate elements of LIST are determined by `equal', or by
+`-compare-fn' if that is non-nil."
+  (declare (important-return-value t))
+  (cond ((null list) (list ()))
+        ;; Optimization: a traversal of `list' is faster than the
+        ;; round trip via `dash--uniq-perms' or `dash--multi-perms'.
+        ((dash--numbers<= list)
+         (dash--lex-perms (vconcat list)))
+        ((let ((freqs (-frequencies list)))
+           ;; Is each element distinct?
+           (unless (--every (= (cdr it) 1) freqs)
+             (dash--multi-perms list freqs))))
+        ((dash--uniq-perms list))))
+
+(defun -inits (list)
+  "Return all prefixes of LIST."
+  (declare (pure t) (side-effect-free t))
+  (let ((res (list list)))
+    (setq list (reverse list))
+    (while list
+      (push (reverse (!cdr list)) res))
+    res))
+
+(defun -tails (list)
+  "Return all suffixes of LIST."
+  (declare (pure t) (side-effect-free t))
+  (-reductions-r-from #'cons nil list))
+
+(defun -common-prefix (&rest lists)
+  "Return the longest common prefix of LISTS."
+  (declare (pure t) (side-effect-free t))
+  (--reduce (--take-while (and acc (equal (pop acc) it)) it)
+            lists))
+
+(defun -common-suffix (&rest lists)
+  "Return the longest common suffix of LISTS."
+  (declare (pure t) (side-effect-free t))
+  (nreverse (apply #'-common-prefix (mapcar #'reverse lists))))
+
+(defun -contains? (list element)
+  "Return non-nil if LIST contains ELEMENT.
+
+The test for equality is done with `equal', or with `-compare-fn'
+if that is non-nil.  As with `member', the return value is
+actually the tail of LIST whose car is ELEMENT.
+
+Alias: `-contains-p'."
+  (declare (important-return-value t))
+  (funcall (dash--member-fn) element list))
+
+(defalias '-contains-p #'-contains?)
+
+(defun -same-items? (list1 list2)
+  "Return non-nil if LIST1 and LIST2 have the same distinct elements.
+
+The order of the elements in the lists does not matter.  The
+lists may be of different lengths, i.e., contain duplicate
+elements.  The test for equality is done with `equal', or with
+`-compare-fn' if that is non-nil.
+
+Alias: `-same-items-p'."
+  (declare (important-return-value t))
+  (let (test len1 len2)
+    (cond ((null (or list1 list2)))
+          ((null (and list1 list2)) nil)
+          ;; Use a hash table if `-compare-fn' is a known hash table
+          ;; test function and either list is long enough.
+          ((and (setq test (dash--hash-test-fn))
+                (setq len1 (length list1))
+                (setq len2 (length list2))
+                (> (max len1 len2) dash--short-list-length))
+           (let ((ht1 (make-hash-table :test test :size len1))
+                 (ht2 (make-hash-table :test test :size len2)))
+             (--each list1 (puthash it t ht1))
+             ;; Move visited elements from `ht1' to `ht2'.  This way,
+             ;; if visiting all of `list2' leaves `ht1' empty, then
+             ;; all elements from both lists have been accounted for.
+             (and (--every (cond ((gethash it ht1)
+                                  (remhash it ht1)
+                                  (puthash it t ht2))
+                                 ((gethash it ht2)))
+                           list2)
+                  (zerop (hash-table-count ht1)))))
+          ((let ((member (dash--member-fn)))
+             (and (--all? (funcall member it list2) list1)
+                  (--all? (funcall member it list1) list2)))))))
+
+(defalias '-same-items-p #'-same-items?)
+
+(defun -is-prefix? (prefix list)
+  "Return non-nil if PREFIX is a prefix of LIST.
+
+Alias: `-is-prefix-p'."
+  (declare (pure t) (side-effect-free t))
+  (--each-while list (and (equal (car prefix) it)
+                          (!cdr prefix)))
+  (null prefix))
+
+(defun -is-suffix? (suffix list)
+  "Return non-nil if SUFFIX is a suffix of LIST.
+
+Alias: `-is-suffix-p'."
+  (declare (pure t) (side-effect-free t))
+  (equal suffix (last list (length suffix))))
+
+(defun -is-infix? (infix list)
+  "Return non-nil if INFIX is infix of LIST.
+
+This operation runs in O(n^2) time
+
+Alias: `-is-infix-p'"
+  (declare (pure t) (side-effect-free t))
+  (let (done)
+    (while (and (not done) list)
+      (setq done (-is-prefix? infix list))
+      (!cdr list))
+    done))
+
+(defalias '-is-prefix-p '-is-prefix?)
+(defalias '-is-suffix-p '-is-suffix?)
+(defalias '-is-infix-p '-is-infix?)
+
+(defun -sort (comparator list)
+  "Sort LIST, stably, comparing elements using COMPARATOR.
+Return the sorted list.  LIST is NOT modified by side effects.
+COMPARATOR is called with two elements of LIST, and should return non-nil
+if the first element should sort before the second."
+  (declare (important-return-value t))
+  (static-if (condition-case nil (sort []) (wrong-number-of-arguments))
+      ;; Since Emacs 30.
+      (sort list :lessp comparator)
+    (sort (copy-sequence list) comparator)))
+
+(defmacro --sort (form list)
+  "Anaphoric form of `-sort'."
+  (declare (debug (def-form form)))
+  `(-sort (lambda (it other) (ignore it other) ,form) ,list))
+
+(defun -list (&optional arg &rest args)
+  "Ensure ARG is a list.
+If ARG is already a list, return it as is (not a copy).
+Otherwise, return a new list with ARG as its only element.
+
+Another supported calling convention is (-list &rest ARGS).
+In this case, if ARG is not a list, a new list with all of
+ARGS as elements is returned.  This use is supported for
+backward compatibility and is otherwise deprecated."
+  (declare (advertised-calling-convention (arg) "2.18.0")
+           (pure t) (side-effect-free error-free))
+  (if (listp arg) arg (cons arg args)))
+
+(defun -repeat (n x)
+  "Return a new list of length N with each element being X.
+Return nil if N is less than 1."
+  (declare (side-effect-free t))
+  (and (>= n 0) (make-list n x)))
+
+(defun -sum (list)
+  "Return the sum of LIST."
+  (declare (pure t) (side-effect-free t))
+  (apply #'+ list))
+
+(defun -running-sum (list)
+  "Return a list with running sums of items in LIST.
+LIST must be non-empty."
+  (declare (pure t) (side-effect-free t))
+  (or list (signal 'wrong-type-argument (list #'consp list)))
+  (-reductions #'+ list))
+
+(defun -product (list)
+  "Return the product of LIST."
+  (declare (pure t) (side-effect-free t))
+  (apply #'* list))
+
+(defun -running-product (list)
+  "Return a list with running products of items in LIST.
+LIST must be non-empty."
+  (declare (pure t) (side-effect-free t))
+  (or list (signal 'wrong-type-argument (list #'consp list)))
+  (-reductions #'* list))
+
+(defun -max (list)
+  "Return the largest value from LIST of numbers or markers."
+  (declare (pure t) (side-effect-free t))
+  (apply #'max list))
+
+(defun -min (list)
+  "Return the smallest value from LIST of numbers or markers."
+  (declare (pure t) (side-effect-free t))
+  (apply #'min list))
+
+(defun -max-by (comparator list)
+  "Take a comparison function COMPARATOR and a LIST and return
+the greatest element of the list by the comparison function.
+
+See also combinator `-on' which can transform the values before
+comparing them."
+  (declare (important-return-value t))
+  (--reduce (if (funcall comparator it acc) it acc) list))
+
+(defun -min-by (comparator list)
+  "Take a comparison function COMPARATOR and a LIST and return
+the least element of the list by the comparison function.
+
+See also combinator `-on' which can transform the values before
+comparing them."
+  (declare (important-return-value t))
+  (--reduce (if (funcall comparator it acc) acc it) list))
+
+(defmacro --max-by (form list)
+  "Anaphoric version of `-max-by'.
+
+The items for the comparator form are exposed as \"it\" and \"other\"."
+  (declare (debug (def-form form)))
+  `(-max-by (lambda (it other) (ignore it other) ,form) ,list))
+
+(defmacro --min-by (form list)
+  "Anaphoric version of `-min-by'.
+
+The items for the comparator form are exposed as \"it\" and \"other\"."
+  (declare (debug (def-form form)))
+  `(-min-by (lambda (it other) (ignore it other) ,form) ,list))
+
+(defun -iota (count &optional start step)
+  "Return a list containing COUNT numbers.
+Starts from START and adds STEP each time.  The default START is
+zero, the default STEP is 1.
+This function takes its name from the corresponding primitive in
+the APL language."
+  (declare (side-effect-free t))
+  (unless (natnump count)
+    (signal 'wrong-type-argument (list #'natnump count)))
+  (or start (setq start 0))
+  (or step (setq step 1))
+  (if (zerop step)
+      (make-list count start)
+    (--iterate (+ it step) start count)))
+
+(defun -fix (fn list)
+  "Compute the (least) fixpoint of FN with initial input LIST.
+
+FN is called at least once, results are compared with `equal'."
+  (declare (important-return-value t))
+  (let ((re (funcall fn list)))
+    (while (not (equal list re))
+      (setq list re)
+      (setq re (funcall fn re)))
+    re))
+
+(defmacro --fix (form list)
+  "Anaphoric form of `-fix'."
+  (declare (debug (def-form form)))
+  `(-fix (lambda (it) (ignore it) ,form) ,list))
+
+(defun -unfold (fun seed)
+  "Build a list from SEED using FUN.
+
+This is \"dual\" operation to `-reduce-r': while -reduce-r
+consumes a list to produce a single value, `-unfold' takes a
+seed value and builds a (potentially infinite!) list.
+
+FUN should return nil to stop the generating process, or a
+cons (A . B), where A will be prepended to the result and B is
+the new seed."
+  (declare (important-return-value t))
+  (let ((last (funcall fun seed)) r)
+    (while last
+      (push (car last) r)
+      (setq last (funcall fun (cdr last))))
+    (nreverse r)))
+
+(defmacro --unfold (form seed)
+  "Anaphoric version of `-unfold'."
+  (declare (debug (def-form form)))
+  `(-unfold (lambda (it) (ignore it) ,form) ,seed))
+
+(defun -cons-pair? (obj)
+  "Return non-nil if OBJ is a true cons pair.
+That is, a cons (A . B) where B is not a list.
+
+Alias: `-cons-pair-p'."
+  (declare (pure t) (side-effect-free error-free))
+  (nlistp (cdr-safe obj)))
+
+(defalias '-cons-pair-p '-cons-pair?)
+
+(defun -cons-to-list (con)
+  "Convert a cons pair to a list with `car' and `cdr' of the pair respectively."
+  (declare (pure t) (side-effect-free t))
+  (list (car con) (cdr con)))
+
+(defun -value-to-list (val)
+  "Convert a value to a list.
+
+If the value is a cons pair, make a list with two elements, `car'
+and `cdr' of the pair respectively.
+
+If the value is anything else, wrap it in a list."
+  (declare (pure t) (side-effect-free t))
+  (if (-cons-pair? val) (-cons-to-list val) (list val)))
+
+(defun -tree-mapreduce-from (fn folder init-value tree)
+  "Apply FN to each element of TREE, and make a list of the results.
+If elements of TREE are lists themselves, apply FN recursively to
+elements of these nested lists.
+
+Then reduce the resulting lists using FOLDER and initial value
+INIT-VALUE. See `-reduce-r-from'.
+
+This is the same as calling `-tree-reduce-from' after `-tree-map'
+but is twice as fast as it only traverse the structure once."
+  (declare (important-return-value t))
+  (cond
+   ((null tree) ())
+   ((-cons-pair? tree) (funcall fn tree))
+   ((consp tree)
+    (-reduce-r-from
+     folder init-value
+     (mapcar (lambda (x) (-tree-mapreduce-from fn folder init-value x)) tree)))
+   ((funcall fn tree))))
+
+(defmacro --tree-mapreduce-from (form folder init-value tree)
+  "Anaphoric form of `-tree-mapreduce-from'."
+  (declare (debug (def-form def-form form form)))
+  `(-tree-mapreduce-from (lambda (it) (ignore it) ,form)
+                         (lambda (it acc) (ignore it acc) ,folder)
+                         ,init-value
+                         ,tree))
+
+(defun -tree-mapreduce (fn folder tree)
+  "Apply FN to each element of TREE, and make a list of the results.
+If elements of TREE are lists themselves, apply FN recursively to
+elements of these nested lists.
+
+Then reduce the resulting lists using FOLDER and initial value
+INIT-VALUE. See `-reduce-r-from'.
+
+This is the same as calling `-tree-reduce' after `-tree-map'
+but is twice as fast as it only traverse the structure once."
+  (declare (important-return-value t))
+  (cond
+   ((null tree) ())
+   ((-cons-pair? tree) (funcall fn tree))
+   ((consp tree)
+    (-reduce-r folder (mapcar (lambda (x) (-tree-mapreduce fn folder x)) tree)))
+   ((funcall fn tree))))
+
+(defmacro --tree-mapreduce (form folder tree)
+  "Anaphoric form of `-tree-mapreduce'."
+  (declare (debug (def-form def-form form)))
+  `(-tree-mapreduce (lambda (it) (ignore it) ,form)
+                    (lambda (it acc) (ignore it acc) ,folder)
+                    ,tree))
+
+(defun -tree-map (fn tree)
+  "Apply FN to each element of TREE while preserving the tree structure."
+  (declare (important-return-value t))
+  (cond
+   ((null tree) ())
+   ((-cons-pair? tree) (funcall fn tree))
+   ((consp tree)
+    (mapcar (lambda (x) (-tree-map fn x)) tree))
+   ((funcall fn tree))))
+
+(defmacro --tree-map (form tree)
+  "Anaphoric form of `-tree-map'."
+  (declare (debug (def-form form)))
+  `(-tree-map (lambda (it) (ignore it) ,form) ,tree))
+
+(defun -tree-reduce-from (fn init-value tree)
+  "Use FN to reduce elements of list TREE.
+If elements of TREE are lists themselves, apply the reduction recursively.
+
+FN is first applied to INIT-VALUE and first element of the list,
+then on this result and second element from the list etc.
+
+The initial value is ignored on cons pairs as they always contain
+two elements."
+  (declare (important-return-value t))
+  (cond
+   ((null tree) ())
+   ((-cons-pair? tree) tree)
+   ((consp tree)
+    (-reduce-r-from
+     fn init-value
+     (mapcar (lambda (x) (-tree-reduce-from fn init-value x)) tree)))
+   (tree)))
+
+(defmacro --tree-reduce-from (form init-value tree)
+  "Anaphoric form of `-tree-reduce-from'."
+  (declare (debug (def-form form form)))
+  `(-tree-reduce-from (lambda (it acc) (ignore it acc) ,form)
+                      ,init-value ,tree))
+
+(defun -tree-reduce (fn tree)
+  "Use FN to reduce elements of list TREE.
+If elements of TREE are lists themselves, apply the reduction recursively.
+
+FN is first applied to first element of the list and second
+element, then on this result and third element from the list etc.
+
+See `-reduce-r' for how exactly are lists of zero or one element handled."
+  (declare (important-return-value t))
+  (cond
+   ((null tree) ())
+   ((-cons-pair? tree) tree)
+   ((consp tree)
+    (-reduce-r fn (mapcar (lambda (x) (-tree-reduce fn x)) tree)))
+   (tree)))
+
+(defmacro --tree-reduce (form tree)
+  "Anaphoric form of `-tree-reduce'."
+  (declare (debug (def-form form)))
+  `(-tree-reduce (lambda (it acc) (ignore it acc) ,form) ,tree))
+
+(defun -tree-map-nodes (pred fun tree)
+  "Call FUN on each node of TREE that satisfies PRED.
+
+If PRED returns nil, continue descending down this node.  If PRED
+returns non-nil, apply FUN to this node and do not descend
+further."
+  (cond ((funcall pred tree) (funcall fun tree))
+        ((and (listp tree) (listp (cdr tree)))
+         (-map (lambda (x) (-tree-map-nodes pred fun x)) tree))
+        (tree)))
+
+(defmacro --tree-map-nodes (pred form tree)
+  "Anaphoric form of `-tree-map-nodes'."
+  (declare (debug (def-form def-form form)))
+  `(-tree-map-nodes (lambda (it) (ignore it) ,pred)
+                    (lambda (it) (ignore it) ,form)
+                    ,tree))
+
+(defun -tree-seq (branch children tree)
+  "Return a sequence of the nodes in TREE, in depth-first search order.
+
+BRANCH is a predicate of one argument that returns non-nil if the
+passed argument is a branch, that is, a node that can have children.
+
+CHILDREN is a function of one argument that returns the children
+of the passed branch node.
+
+Non-branch nodes are simply copied."
+  (declare (important-return-value t))
+  (cons tree
+        (and (funcall branch tree)
+             (-mapcat (lambda (x) (-tree-seq branch children x))
+                      (funcall children tree)))))
+
+(defmacro --tree-seq (branch children tree)
+  "Anaphoric form of `-tree-seq'."
+  (declare (debug (def-form def-form form)))
+  `(-tree-seq (lambda (it) (ignore it) ,branch)
+              (lambda (it) (ignore it) ,children)
+              ,tree))
+
+(defun -clone (list)
+  "Create a deep copy of LIST.
+The new list has the same elements and structure but all cons are
+replaced with new ones.  This is useful when you need to clone a
+structure such as plist or alist."
+  (declare (side-effect-free t))
+  (-tree-map #'identity list))
+\f
+;;; Combinators
+
+(defalias '-partial #'apply-partially
+  "Return a function that is a partial application of FUN to ARGS.
+ARGS is a list of the first N arguments to pass to FUN.
+The result is a new function which does the same as FUN, except that
+the first N arguments are fixed at the values with which this function
+was called.
+\n(fn FUN &rest ARGS)")
+
+(defun -rpartial (fn &rest args)
+  "Return a function that is a partial application of FN to ARGS.
+ARGS is a list of the last N arguments to pass to FN.  The result
+is a new function which does the same as FN, except that the last
+N arguments are fixed at the values with which this function was
+called.  This is like `-partial', except the arguments are fixed
+starting from the right rather than the left."
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (&rest args-before) (apply fn (append args-before args))))
+
+(defun -juxt (&rest fns)
+  "Return a function that is the juxtaposition of FNS.
+The returned function takes a variable number of ARGS, applies
+each of FNS in turn to ARGS, and returns the list of results."
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (&rest args) (mapcar (lambda (x) (apply x args)) fns)))
+
+(defun -compose (&rest fns)
+  "Compose FNS into a single composite function.
+Return a function that takes a variable number of ARGS, applies
+the last function in FNS to ARGS, and returns the result of
+calling each remaining function on the result of the previous
+function, right-to-left.  If no FNS are given, return a variadic
+`identity' function."
+  (declare (pure t) (side-effect-free error-free))
+  (let* ((fns (nreverse fns))
+         (head (car fns))
+         (tail (cdr fns)))
+    (cond (tail
+           (lambda (&rest args)
+             (--reduce-from (funcall it acc) (apply head args) tail)))
+          (fns head)
+          ((lambda (&optional arg &rest _) arg)))))
+
+(defun -applify (fn)
+  "Return a function that applies FN to a single list of args.
+This changes the arity of FN from taking N distinct arguments to
+taking 1 argument which is a list of N arguments."
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (args) (apply fn args)))
+
+(defun -on (op trans)
+  "Return a function that calls TRANS on each arg and OP on the results.
+The returned function takes a variable number of arguments, calls
+the function TRANS on each one in turn, and then passes those
+results as the list of arguments to OP, in the same order.
+
+For example, the following pairs of expressions are morally
+equivalent:
+
+  (funcall (-on #\\='+ #\\='1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
+  (funcall (-on #\\='+ #\\='1+))       = (+)"
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (&rest args)
+    ;; This unrolling seems to be a relatively cheap way to keep the
+    ;; overhead of `mapcar' + `apply' in check.
+    (cond ((cddr args)
+           (apply op (mapcar trans args)))
+          ((cdr args)
+           (funcall op (funcall trans (car args)) (funcall trans (cadr args))))
+          (args
+           (funcall op (funcall trans (car args))))
+          ((funcall op)))))
+
+(defun -flip (fn)
+  "Return a function that calls FN with its arguments reversed.
+The returned function takes the same number of arguments as FN.
+
+For example, the following two expressions are morally
+equivalent:
+
+  (funcall (-flip #\\='-) 1 2) = (- 2 1)
+
+See also: `-rotate-args'."
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (&rest args) ;; Open-code for speed.
+    (cond ((cddr args) (apply fn (nreverse args)))
+          ((cdr args) (funcall fn (cadr args) (car args)))
+          (args (funcall fn (car args)))
+          ((funcall fn)))))
+
+(defun -rotate-args (n fn)
+  "Return a function that calls FN with args rotated N places to the right.
+The returned function takes the same number of arguments as FN,
+rotates the list of arguments N places to the right (left if N is
+negative) just like `-rotate', and applies FN to the result.
+
+See also: `-flip'."
+  (declare (pure t) (side-effect-free t))
+  (if (zerop n)
+      fn
+    (let ((even (= (% n 2) 0)))
+      (lambda (&rest args)
+        (cond ((cddr args) ;; Open-code for speed.
+               (apply fn (-rotate n args)))
+              ((cdr args)
+               (let ((fst (car args))
+                     (snd (cadr args)))
+                 (funcall fn (if even fst snd) (if even snd fst))))
+              (args
+               (funcall fn (car args)))
+              ((funcall fn)))))))
+
+(defun -const (c)
+  "Return a function that returns C ignoring any additional arguments.
+
+In types: a -> b -> a"
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (&rest _) c))
+
+(defmacro -cut (&rest params)
+  "Take n-ary function and n arguments and specialize some of them.
+Arguments denoted by <> will be left unspecialized.
+
+See SRFI-26 for detailed description."
+  (declare (debug (&optional sexp &rest &or "<>" form)))
+  (let* ((i 0)
+         (args (--keep (when (eq it '<>)
+                         (setq i (1+ i))
+                         (make-symbol (format "D%d" i)))
+                       params)))
+    `(lambda ,args
+       ,(let ((body (--map (if (eq it '<>) (pop args) it) params)))
+          (if (eq (car params) '<>)
+              (cons #'funcall body)
+            body)))))
+
+(defun -not (pred)
+  "Return a predicate that negates the result of PRED.
+The returned predicate passes its arguments to PRED.  If PRED
+returns nil, the result is non-nil; otherwise the result is nil.
+
+See also: `-andfn' and `-orfn'."
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (&rest args) (not (apply pred args))))
+
+(defun -orfn (&rest preds)
+  "Return a predicate that returns the first non-nil result of PREDS.
+The returned predicate takes a variable number of arguments,
+passes them to each predicate in PREDS in turn until one of them
+returns non-nil, and returns that non-nil result without calling
+the remaining PREDS.  If all PREDS return nil, or if no PREDS are
+given, the returned predicate returns nil.
+
+See also: `-andfn' and `-not'."
+  (declare (pure t) (side-effect-free error-free))
+  ;; Open-code for speed.
+  (cond ((cdr preds) (lambda (&rest args) (--some (apply it args) preds)))
+        (preds (car preds))
+        (#'ignore)))
+
+(defun -andfn (&rest preds)
+  "Return a predicate that returns non-nil if all PREDS do so.
+The returned predicate P takes a variable number of arguments and
+passes them to each predicate in PREDS in turn.  If any one of
+PREDS returns nil, P also returns nil without calling the
+remaining PREDS.  If all PREDS return non-nil, P returns the last
+such value.  If no PREDS are given, P always returns non-nil.
+
+See also: `-orfn' and `-not'."
+  (declare (pure t) (side-effect-free error-free))
+  ;; Open-code for speed.
+  (cond ((cdr preds) (lambda (&rest args) (--every (apply it args) preds)))
+        (preds (car preds))
+        ((static-if (fboundp 'always)
+             #'always
+           (lambda (&rest _) t)))))
+
+(defun -iteratefn (fn n)
+  "Return a function FN composed N times with itself.
+
+FN is a unary function.  If you need to use a function of higher
+arity, use `-applify' first to turn it into a unary function.
+
+With n = 0, this acts as identity function.
+
+In types: (a -> a) -> Int -> a -> a.
+
+This function satisfies the following law:
+
+  (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n)))."
+  (declare (pure t) (side-effect-free error-free))
+  (lambda (x) (--dotimes n (setq x (funcall fn x))) x))
+
+(defun -counter (&optional beg end inc)
+  "Return a closure that counts from BEG to END, with increment INC.
+
+The closure will return the next value in the counting sequence
+each time it is called, and nil after END is reached. BEG
+defaults to 0, INC defaults to 1, and if END is nil, the counter
+will increment indefinitely.
+
+The closure accepts any number of arguments, which are discarded."
+  (declare (pure t) (side-effect-free error-free))
+  (let ((inc (or inc 1))
+        (n (or beg 0)))
+    (lambda (&rest _)
+      (when (or (not end) (< n end))
+        (prog1 n
+          (setq n (+ n inc)))))))
+
+(defvar -fixfn-max-iterations 1000
+  "The default maximum number of iterations performed by `-fixfn'
+  unless otherwise specified.")
+
+(defun -fixfn (fn &optional equal-test halt-test)
+  "Return a function that computes the (least) fixpoint of FN.
+
+FN must be a unary function. The returned lambda takes a single
+argument, X, the initial value for the fixpoint iteration. The
+iteration halts when either of the following conditions is satisfied:
+
+ 1. Iteration converges to the fixpoint, with equality being
+    tested using EQUAL-TEST. If EQUAL-TEST is not specified,
+    `equal' is used. For functions over the floating point
+    numbers, it may be necessary to provide an appropriate
+    approximate comparison test.
+
+ 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a
+    simple counter that returns t after `-fixfn-max-iterations',
+    to guard against infinite iteration. Otherwise, HALT-TEST
+    must be a function that accepts a single argument, the
+    current value of X, and returns non-nil as long as iteration
+    should continue. In this way, a more sophisticated
+    convergence test may be supplied by the caller.
+
+The return value of the lambda is either the fixpoint or, if
+iteration halted before converging, a cons with car `halted' and
+cdr the final output from HALT-TEST.
+
+In types: (a -> a) -> a -> a."
+  (declare (important-return-value t))
+  (let ((eqfn   (or equal-test 'equal))
+        (haltfn (or halt-test
+                    (-not
+                     (-counter 0 -fixfn-max-iterations)))))
+    (lambda (x)
+      (let ((re (funcall fn x))
+            (halt? (funcall haltfn x)))
+        (while (and (not halt?) (not (funcall eqfn x re)))
+          (setq x     re
+                re    (funcall fn re)
+                halt? (funcall haltfn re)))
+        (if halt? (cons 'halted halt?)
+          re)))))
+
+(defun -prodfn (&rest fns)
+  "Return a function that applies each of FNS to each of a list of arguments.
+
+Takes a list of N functions and returns a function that takes a
+list of length N, applying Ith function to Ith element of the
+input list.  Returns a list of length N.
+
+In types (for N=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d)
+
+This function satisfies the following laws:
+
+    (-compose (-prodfn f g ...)
+              (-prodfn f\\=' g\\=' ...))
+  = (-prodfn (-compose f f\\=')
+             (-compose g g\\=')
+             ...)
+
+    (-prodfn f g ...)
+  = (-juxt (-compose f (-partial #\\='nth 0))
+           (-compose g (-partial #\\='nth 1))
+           ...)
+
+    (-compose (-prodfn f g ...)
+              (-juxt f\\=' g\\=' ...))
+  = (-juxt (-compose f f\\=')
+           (-compose g g\\=')
+           ...)
+
+    (-compose (-partial #\\='nth n)
+              (-prod f1 f2 ...))
+  = (-compose fn (-partial #\\='nth n))"
+  (declare (pure t) (side-effect-free t))
+  (lambda (x) (--zip-with (funcall it other) fns x)))
+\f
+;;; Font lock
+
+(defvar dash--keywords
+  `(;; TODO: Do not fontify the following automatic variables
+    ;; globally; detect and limit to their local anaphoric scope.
+    (,(rx symbol-start (| "acc" "it" "it-index" "other") symbol-end)
+     . 'font-lock-variable-name-face)
+    ;; Macros in dev/examples.el.  Based on `lisp-mode-symbol-regexp'.
+    (,(rx ?\( (group (| "defexamples" "def-example-group")) symbol-end
+          (+ (in "\t "))
+          (group (* (| (syntax word) (syntax symbol) (: ?\\ nonl)))))
+     (1 'font-lock-keyword-face)
+     (2 'font-lock-function-name-face))
+    ;; Symbols in dev/examples.el.
+    ,(rx symbol-start (| "=>" "~>" "!!>") symbol-end)
+    ;; Elisp macro fontification was static prior to Emacs 25.
+    ,@(when (< emacs-major-version 25)
+        (let ((macs '("!cdr"
+                      "!cons"
+                      "-->"
+                      "--all-p"
+                      "--all?"
+                      "--annotate"
+                      "--any"
+                      "--any-p"
+                      "--any?"
+                      "--count"
+                      "--dotimes"
+                      "--doto"
+                      "--drop-while"
+                      "--each"
+                      "--each-indexed"
+                      "--each-r"
+                      "--each-r-while"
+                      "--each-while"
+                      "--every"
+                      "--every-p"
+                      "--every?"
+                      "--filter"
+                      "--find"
+                      "--find-index"
+                      "--find-indices"
+                      "--find-last-index"
+                      "--first"
+                      "--fix"
+                      "--group-by"
+                      "--if-let"
+                      "--iterate"
+                      "--keep"
+                      "--last"
+                      "--map"
+                      "--map-first"
+                      "--map-indexed"
+                      "--map-last"
+                      "--map-when"
+                      "--mapcat"
+                      "--max-by"
+                      "--min-by"
+                      "--none-p"
+                      "--none?"
+                      "--only-some-p"
+                      "--only-some?"
+                      "--partition-after-pred"
+                      "--partition-by"
+                      "--partition-by-header"
+                      "--reduce"
+                      "--reduce-from"
+                      "--reduce-r"
+                      "--reduce-r-from"
+                      "--reductions"
+                      "--reductions-from"
+                      "--reductions-r"
+                      "--reductions-r-from"
+                      "--reject"
+                      "--reject-first"
+                      "--reject-last"
+                      "--remove"
+                      "--remove-first"
+                      "--remove-last"
+                      "--replace-where"
+                      "--select"
+                      "--separate"
+                      "--some"
+                      "--some-p"
+                      "--some?"
+                      "--sort"
+                      "--splice"
+                      "--splice-list"
+                      "--split-when"
+                      "--split-with"
+                      "--take-while"
+                      "--tree-map"
+                      "--tree-map-nodes"
+                      "--tree-mapreduce"
+                      "--tree-mapreduce-from"
+                      "--tree-reduce"
+                      "--tree-reduce-from"
+                      "--tree-seq"
+                      "--unfold"
+                      "--update-at"
+                      "--when-let"
+                      "--zip-with"
+                      "->"
+                      "->>"
+                      "-as->"
+                      "-cut"
+                      "-doto"
+                      "-if-let"
+                      "-if-let*"
+                      "-lambda"
+                      "-let"
+                      "-let*"
+                      "-setq"
+                      "-some-->"
+                      "-some->"
+                      "-some->>"
+                      "-split-on"
+                      "-when-let"
+                      "-when-let*")))
+          `((,(concat "(" (regexp-opt macs 'symbols)) . 1)))))
+  "Font lock keywords for `dash-fontify-mode'.")
+
+(defcustom dash-fontify-mode-lighter nil
+  "Mode line lighter for `dash-fontify-mode'.
+Either a string to display in the mode line when
+`dash-fontify-mode' is on, or nil to display
+nothing (the default)."
+  :package-version '(dash . "2.18.0")
+  :type '(choice (string :tag "Lighter" :value " Dash")
+                 (const :tag "Nothing" nil)))
+
+;;;###autoload
+(define-minor-mode dash-fontify-mode
+  "Toggle fontification of Dash special variables.
+
+Dash-Fontify mode is a buffer-local minor mode intended for Emacs
+Lisp buffers.  Enabling it causes the special variables bound in
+anaphoric Dash macros to be fontified.  These anaphoras include
+`it', `it-index', `acc', and `other'.  In older Emacs versions
+which do not dynamically detect macros, Dash-Fontify mode
+additionally fontifies Dash macro calls.
+
+See also `dash-fontify-mode-lighter' and
+`global-dash-fontify-mode'."
+  :lighter dash-fontify-mode-lighter
+  (if dash-fontify-mode
+      (font-lock-add-keywords nil dash--keywords t)
+    (font-lock-remove-keywords nil dash--keywords))
+  (static-if (fboundp 'font-lock-flush)
+      ;; Added in Emacs 25.
+      (font-lock-flush)
+    (when font-lock-mode
+      ;; Unconditionally enables `font-lock-mode' and is marked
+      ;; `interactive-only' in later Emacs versions which have
+      ;; `font-lock-flush'.
+      (font-lock-fontify-buffer))))
+
+(defun dash--turn-on-fontify-mode ()
+  "Enable `dash-fontify-mode' if in an Emacs Lisp buffer."
+  (when (derived-mode-p #'emacs-lisp-mode)
+    (dash-fontify-mode)))
+
+;;;###autoload
+(define-globalized-minor-mode global-dash-fontify-mode
+  dash-fontify-mode dash--turn-on-fontify-mode)
+
+(defcustom dash-enable-fontlock nil
+  "If non-nil, fontify Dash macro calls and special variables."
+  :set (lambda (sym val)
+         (set-default sym val)
+         (global-dash-fontify-mode (if val 1 0)))
+  :type 'boolean)
+
+(make-obsolete-variable
+ 'dash-enable-fontlock #'global-dash-fontify-mode "2.18.0")
+
+(define-obsolete-function-alias
+  'dash-enable-font-lock #'global-dash-fontify-mode "2.18.0")
+\f
+;;; Info
+
+(defvar dash--info-doc-spec '("(dash) Index" nil "^ -+ .*: " "\\( \\|$\\)")
+  "The Dash :doc-spec entry for `info-lookup-alist'.
+It is based on that for `emacs-lisp-mode'.")
+
+(defun dash--info-elisp-docs ()
+  "Return the `emacs-lisp-mode' symbol docs from `info-lookup-alist'.
+Specifically, return the cons containing their
+`info-lookup->doc-spec' so that we can modify it."
+  (defvar info-lookup-alist)
+  (nthcdr 3 (assq #'emacs-lisp-mode (cdr (assq 'symbol info-lookup-alist)))))
+
+;;;###autoload
+(defun dash-register-info-lookup ()
+  "Register the Dash Info manual with `info-lookup-symbol'.
+This allows Dash symbols to be looked up with \\[info-lookup-symbol]."
+  (interactive)
+  (require 'info-look)
+  (let ((docs (dash--info-elisp-docs)))
+    (setcar docs (append (car docs) (list dash--info-doc-spec)))
+    (info-lookup-reset)))
+
+(defun dash-unload-function ()
+  "Remove Dash from `info-lookup-alist'.
+Used by `unload-feature', which see."
+  (let ((docs (and (featurep 'info-look)
+                   (dash--info-elisp-docs))))
+    (when (member dash--info-doc-spec (car docs))
+      (setcar docs (remove dash--info-doc-spec (car docs)))
+      (info-lookup-reset)))
+  nil)
+
+(provide 'dash)
+;;; dash.el ends here
diff --git a/elpa/dash-20250312.1307/dash.info b/elpa/dash-20250312.1307/dash.info
new file mode 100644 (file)
index 0000000..6c0ef89
--- /dev/null
@@ -0,0 +1,4954 @@
+This is dash.info, produced by makeinfo version 6.8 from dash.texi.
+
+This manual is for Dash version 2.20.0.
+
+   Copyright © 2012–2025 Free Software Foundation, Inc.
+
+     Permission is granted to copy, distribute and/or modify this
+     document under the terms of the GNU Free Documentation License,
+     Version 1.3 or any later version published by the Free Software
+     Foundation; with the Invariant Sections being “GNU General Public
+     License,” and no Front-Cover Texts or Back-Cover Texts.  A copy of
+     the license is included in the section entitled “GNU Free
+     Documentation License”.
+INFO-DIR-SECTION Emacs
+START-INFO-DIR-ENTRY
+* Dash: (dash.info).    A modern list library for GNU Emacs.
+END-INFO-DIR-ENTRY
+
+\1f
+File: dash.info,  Node: Top,  Next: Installation,  Up: (dir)
+
+Dash
+****
+
+This manual is for Dash version 2.20.0.
+
+   Copyright © 2012–2025 Free Software Foundation, Inc.
+
+     Permission is granted to copy, distribute and/or modify this
+     document under the terms of the GNU Free Documentation License,
+     Version 1.3 or any later version published by the Free Software
+     Foundation; with the Invariant Sections being “GNU General Public
+     License,” and no Front-Cover Texts or Back-Cover Texts.  A copy of
+     the license is included in the section entitled “GNU Free
+     Documentation License”.
+
+* Menu:
+
+* Installation::        Installing and configuring Dash.
+* Functions::           Dash API reference.
+* Development::         Contributing to Dash development.
+
+Appendices
+
+* FDL::                 The license for this documentation.
+* GPL::                 Conditions for copying and changing Dash.
+* Index::               Index including functions and macros.
+
+ — The Detailed Node Listing —
+
+Installation
+
+* Using in a package::  Listing Dash as a package dependency.
+* Fontification of special variables::  Font Lock of anaphoric macro variables.
+* Info symbol lookup::  Looking up Dash symbols in this manual.
+
+Functions
+
+* Maps::
+* Sublist selection::
+* List to list::
+* Reductions::
+* Unfolding::
+* Predicates::
+* Partitioning::
+* Indexing::
+* Set operations::
+* Other list operations::
+* Tree operations::
+* Threading macros::
+* Binding::
+* Side effects::
+* Destructive operations::
+* Function combinators::
+
+Development
+
+* Contribute::          How to contribute.
+* Contributors::        List of contributors.
+
+\1f
+File: dash.info,  Node: Installation,  Next: Functions,  Prev: Top,  Up: Top
+
+1 Installation
+**************
+
+Dash is available on GNU ELPA (https://elpa.gnu.org/), GNU-devel ELPA
+(https://elpa.gnu.org/devel/), and MELPA (https://melpa.org/), and can
+be installed with the standard command ‘package-install’ (*note
+(emacs)Package Installation::).
+
+‘M-x package-install <RET> dash <RET>’
+     Install the Dash library.
+
+   Alternatively, you can just dump ‘dash.el’ in your ‘load-path’
+somewhere (*note (emacs)Lisp Libraries::).
+
+* Menu:
+
+* Using in a package::  Listing Dash as a package dependency.
+* Fontification of special variables::  Font Lock of anaphoric macro variables.
+* Info symbol lookup::  Looking up Dash symbols in this manual.
+
+\1f
+File: dash.info,  Node: Using in a package,  Next: Fontification of special variables,  Up: Installation
+
+1.1 Using in a package
+======================
+
+If you use Dash in your own package, be sure to list it as a dependency
+in the library’s headers as follows (*note (elisp)Library Headers::).
+
+     ;; Package-Requires: ((dash "2.20.0"))
+
+\1f
+File: dash.info,  Node: Fontification of special variables,  Next: Info symbol lookup,  Prev: Using in a package,  Up: Installation
+
+1.2 Fontification of special variables
+======================================
+
+The autoloaded minor mode ‘dash-fontify-mode’ is provided for optional
+fontification of anaphoric Dash variables (‘it’, ‘acc’, etc.) in Emacs
+Lisp buffers using search-based Font Lock (*note (emacs)Font Lock::).
+In older Emacs versions which do not dynamically detect macros, the
+minor mode also fontifies calls to Dash macros.
+
+   To automatically enable the minor mode in all Emacs Lisp buffers,
+just call its autoloaded global counterpart ‘global-dash-fontify-mode’,
+either interactively or from your ‘user-init-file’:
+
+     (global-dash-fontify-mode)
+
+\1f
+File: dash.info,  Node: Info symbol lookup,  Prev: Fontification of special variables,  Up: Installation
+
+1.3 Info symbol lookup
+======================
+
+While editing Elisp files, you can use ‘C-h S’ (‘info-lookup-symbol’) to
+look up Elisp symbols in the relevant Info manuals (*note (emacs)Info
+Lookup::).  To enable the same for Dash symbols, use the command
+‘dash-register-info-lookup’.  It can be called directly when needed, or
+automatically from your ‘user-init-file’.  For example:
+
+     (with-eval-after-load 'info-look
+       (dash-register-info-lookup))
+
+\1f
+File: dash.info,  Node: Functions,  Next: Development,  Prev: Installation,  Up: Top
+
+2 Functions
+***********
+
+This chapter contains reference documentation for the Dash API
+(Application Programming Interface).  The names of all public functions
+defined in the library are prefixed with a dash character (‘-’).
+
+   The library also provides anaphoric macro versions of functions where
+that makes sense.  The names of these macros are prefixed with two
+dashes (‘--’) instead of one.
+
+   For instance, while the function ‘-map’ applies a function to each
+element of a list, its anaphoric counterpart ‘--map’ evaluates a form
+with the local variable ‘it’ temporarily bound to the current list
+element instead.
+
+     ;; Normal version.
+     (-map (lambda (n) (* n n)) '(1 2 3 4))
+         ⇒ (1 4 9 16)
+
+     ;; Anaphoric version.
+     (--map (* it it) '(1 2 3 4))
+         ⇒ (1 4 9 16)
+
+   The normal version can, of course, also be written as in the
+following example, which demonstrates the utility of both versions.
+
+     (defun my-square (n)
+       "Return N multiplied by itself."
+       (* n n))
+
+     (-map #'my-square '(1 2 3 4))
+         ⇒ (1 4 9 16)
+
+* Menu:
+
+* Maps::
+* Sublist selection::
+* List to list::
+* Reductions::
+* Unfolding::
+* Predicates::
+* Partitioning::
+* Indexing::
+* Set operations::
+* Other list operations::
+* Tree operations::
+* Threading macros::
+* Binding::
+* Side effects::
+* Destructive operations::
+* Function combinators::
+
+\1f
+File: dash.info,  Node: Maps,  Next: Sublist selection,  Up: Functions
+
+2.1 Maps
+========
+
+Functions in this category take a transforming function, which is then
+applied sequentially to each or selected elements of the input list.
+The results are collected in order and returned as a new list.
+
+ -- Function: -map (fn list)
+     Apply FN to each item in LIST and return the list of results.
+
+     This function’s anaphoric counterpart is ‘--map’.
+
+          (-map (lambda (num) (* num num)) '(1 2 3 4))
+              ⇒ (1 4 9 16)
+          (-map #'1+ '(1 2 3 4))
+              ⇒ (2 3 4 5)
+          (--map (* it it) '(1 2 3 4))
+              ⇒ (1 4 9 16)
+
+ -- Function: -map-when (pred rep list)
+     Use PRED to conditionally apply REP to each item in LIST.  Return a
+     copy of LIST where the items for which PRED returns ‘nil’ are
+     unchanged, and the rest are mapped through the REP function.
+
+     Alias: ‘-replace-where’
+
+     See also: ‘-update-at’ (*note -update-at::)
+
+          (-map-when 'even? 'square '(1 2 3 4))
+              ⇒ (1 4 3 16)
+          (--map-when (> it 2) (* it it) '(1 2 3 4))
+              ⇒ (1 2 9 16)
+          (--map-when (= it 2) 17 '(1 2 3 4))
+              ⇒ (1 17 3 4)
+
+ -- Function: -map-first (pred rep list)
+     Use PRED to determine the first item in LIST to call REP on.
+     Return a copy of LIST where the first item for which PRED returns
+     non-‘nil’ is replaced with the result of calling REP on that item.
+
+     See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note
+     -replace-first::)
+
+          (-map-first 'even? 'square '(1 2 3 4))
+              ⇒ (1 4 3 4)
+          (--map-first (> it 2) (* it it) '(1 2 3 4))
+              ⇒ (1 2 9 4)
+          (--map-first (= it 2) 17 '(1 2 3 2))
+              ⇒ (1 17 3 2)
+
+ -- Function: -map-last (pred rep list)
+     Use PRED to determine the last item in LIST to call REP on.  Return
+     a copy of LIST where the last item for which PRED returns non-‘nil’
+     is replaced with the result of calling REP on that item.
+
+     See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note
+     -replace-last::)
+
+          (-map-last 'even? 'square '(1 2 3 4))
+              ⇒ (1 2 3 16)
+          (--map-last (> it 2) (* it it) '(1 2 3 4))
+              ⇒ (1 2 3 16)
+          (--map-last (= it 2) 17 '(1 2 3 2))
+              ⇒ (1 2 3 17)
+
+ -- Function: -map-indexed (fn list)
+     Apply FN to each index and item in LIST and return the list of
+     results.  This is like ‘-map’ (*note -map::), but FN takes two
+     arguments: the index of the current element within LIST, and the
+     element itself.
+
+     This function’s anaphoric counterpart is ‘--map-indexed’.
+
+     For a side-effecting variant, see also ‘-each-indexed’ (*note
+     -each-indexed::).
+
+          (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4))
+              ⇒ (1 1 1 1)
+          (--map-indexed (- it it-index) '(1 2 3 4))
+              ⇒ (1 1 1 1)
+          (-map-indexed #'* '(1 2 3 4))
+              ⇒ (0 2 6 12)
+
+ -- Function: -annotate (fn list)
+     Pair each item in LIST with the result of passing it to FN.
+
+     Return an alist of (RESULT .  ITEM), where each ITEM is the
+     corresponding element of LIST, and RESULT is the value obtained by
+     calling FN on ITEM.
+
+     This function’s anaphoric counterpart is ‘--annotate’.
+
+          (-annotate #'1+ '(1 2 3))
+              ⇒ ((2 . 1) (3 . 2) (4 . 3))
+          (-annotate #'length '((f o o) (bar baz)))
+              ⇒ ((3 f o o) (2 bar baz))
+          (--annotate (> it 1) '(0 1 2 3))
+              ⇒ ((nil . 0) (nil . 1) (t . 2) (t . 3))
+
+ -- Function: -splice (pred fun list)
+     Splice lists generated by FUN in place of items satisfying PRED in
+     LIST.
+
+     Call PRED on each element of LIST.  Whenever the result of PRED is
+     ‘nil’, leave that ‘it’ as-is.  Otherwise, call FUN on the same ‘it’
+     that satisfied PRED.  The result should be a (possibly empty) list
+     of items to splice in place of ‘it’ in LIST.
+
+     This can be useful as an alternative to the ‘,@’ construct in a ‘`’
+     structure, in case you need to splice several lists at marked
+     positions (for example with keywords).
+
+     This function’s anaphoric counterpart is ‘--splice’.
+
+     See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’
+     (*note -insert-at::).
+
+          (-splice #'numberp (lambda (n) (list n n)) '(a 1 b 2))
+              ⇒ (a 1 1 b 2 2)
+          (--splice t (list it it) '(1 2 3 4))
+              ⇒ (1 1 2 2 3 3 4 4)
+          (--splice (eq it :magic) '((magical) (code)) '((foo) :magic (bar)))
+              ⇒ ((foo) (magical) (code) (bar))
+
+ -- Function: -splice-list (pred new-list list)
+     Splice NEW-LIST in place of elements matching PRED in LIST.
+
+     See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note
+     -insert-at::)
+
+          (-splice-list 'keywordp '(a b c) '(1 :foo 2))
+              ⇒ (1 a b c 2)
+          (-splice-list 'keywordp nil '(1 :foo 2))
+              ⇒ (1 2)
+          (--splice-list (keywordp it) '(a b c) '(1 :foo 2))
+              ⇒ (1 a b c 2)
+
+ -- Function: -mapcat (fn list)
+     Return the concatenation of the result of mapping FN over LIST.
+     Thus function FN should return a list.
+
+          (-mapcat 'list '(1 2 3))
+              ⇒ (1 2 3)
+          (-mapcat (lambda (item) (list 0 item)) '(1 2 3))
+              ⇒ (0 1 0 2 0 3)
+          (--mapcat (list 0 it) '(1 2 3))
+              ⇒ (0 1 0 2 0 3)
+
+ -- Function: -copy (list)
+     Create a shallow copy of LIST.  The elements of LIST are not
+     copied; they are shared with the original.
+
+          (-copy '(1 2 3))
+              ⇒ (1 2 3)
+          (let ((a '(1 2 3))) (eq a (-copy a)))
+              ⇒ nil
+
+\1f
+File: dash.info,  Node: Sublist selection,  Next: List to list,  Prev: Maps,  Up: Functions
+
+2.2 Sublist selection
+=====================
+
+Functions returning a sublist of the original list.
+
+ -- Function: -filter (pred list)
+     Return a new list of the items in LIST for which PRED returns
+     non-‘nil’.
+
+     Alias: ‘-select’.
+
+     This function’s anaphoric counterpart is ‘--filter’.
+
+     For similar operations, see also ‘-keep’ (*note -keep::) and
+     ‘-remove’ (*note -remove::).
+
+          (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4))
+              ⇒ (2 4)
+          (-filter #'natnump '(-2 -1 0 1 2))
+              ⇒ (0 1 2)
+          (--filter (= 0 (% it 2)) '(1 2 3 4))
+              ⇒ (2 4)
+
+ -- Function: -remove (pred list)
+     Return a new list of the items in LIST for which PRED returns
+     ‘nil’.
+
+     Alias: ‘-reject’.
+
+     This function’s anaphoric counterpart is ‘--remove’.
+
+     For similar operations, see also ‘-keep’ (*note -keep::) and
+     ‘-filter’ (*note -filter::).
+
+          (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4))
+              ⇒ (1 3)
+          (-remove #'natnump '(-2 -1 0 1 2))
+              ⇒ (-2 -1)
+          (--remove (= 0 (% it 2)) '(1 2 3 4))
+              ⇒ (1 3)
+
+ -- Function: -remove-first (pred list)
+     Remove the first item from LIST for which PRED returns non-‘nil’.
+     This is a non-destructive operation, but only the front of LIST
+     leading up to the removed item is a copy; the rest is LIST’s
+     original tail.  If no item is removed, then the result is a
+     complete copy.
+
+     Alias: ‘-reject-first’.
+
+     This function’s anaphoric counterpart is ‘--remove-first’.
+
+     See also ‘-map-first’ (*note -map-first::), ‘-remove-item’ (*note
+     -remove-item::), and ‘-remove-last’ (*note -remove-last::).
+
+          (-remove-first #'natnump '(-2 -1 0 1 2))
+              ⇒ (-2 -1 1 2)
+          (-remove-first #'stringp '(1 2 "first" "second"))
+              ⇒ (1 2 "second")
+          (--remove-first (> it 3) '(1 2 3 4 5 6))
+              ⇒ (1 2 3 5 6)
+
+ -- Function: -remove-last (pred list)
+     Remove the last item from LIST for which PRED returns non-‘nil’.
+     The result is a copy of LIST regardless of whether an element is
+     removed.
+
+     Alias: ‘-reject-last’.
+
+     This function’s anaphoric counterpart is ‘--remove-last’.
+
+     See also ‘-map-last’ (*note -map-last::), ‘-remove-item’ (*note
+     -remove-item::), and ‘-remove-first’ (*note -remove-first::).
+
+          (-remove-last #'natnump '(1 3 5 4 7 8 10 -11))
+              ⇒ (1 3 5 4 7 8 -11)
+          (-remove-last #'stringp '(1 2 "last" "second"))
+              ⇒ (1 2 "last")
+          (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10))
+              ⇒ (1 2 3 4 5 6 7 8 9)
+
+ -- Function: -remove-item (item list)
+     Return a copy of LIST with all occurrences of ITEM removed.  The
+     comparison is done with ‘equal’.
+
+          (-remove-item 3 '(1 2 3 2 3 4 5 3))
+              ⇒ (1 2 2 4 5)
+          (-remove-item 'foo '(foo bar baz foo))
+              ⇒ (bar baz)
+          (-remove-item "bob" '("alice" "bob" "eve" "bob"))
+              ⇒ ("alice" "eve")
+
+ -- Function: -non-nil (list)
+     Return a copy of LIST with all ‘nil’ items removed.
+
+          (-non-nil '(nil 1 nil 2 nil nil 3 4 nil 5 nil))
+              ⇒ (1 2 3 4 5)
+          (-non-nil '((nil)))
+              ⇒ ((nil))
+          (-non-nil ())
+              ⇒ ()
+
+ -- Function: -slice (list from &optional to step)
+     Return copy of LIST, starting from index FROM to index TO.
+
+     FROM or TO may be negative.  These values are then interpreted
+     modulo the length of the list.
+
+     If STEP is a number, only each STEPth item in the resulting section
+     is returned.  Defaults to 1.
+
+          (-slice '(1 2 3 4 5) 1)
+              ⇒ (2 3 4 5)
+          (-slice '(1 2 3 4 5) 0 3)
+              ⇒ (1 2 3)
+          (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2)
+              ⇒ (2 4 6 8)
+
+ -- Function: -take (n list)
+     Return a copy of the first N items in LIST.  Return a copy of LIST
+     if it contains N items or fewer.  Return ‘nil’ if N is zero or
+     less.
+
+     See also: ‘-take-last’ (*note -take-last::).
+
+          (-take 3 '(1 2 3 4 5))
+              ⇒ (1 2 3)
+          (-take 17 '(1 2 3 4 5))
+              ⇒ (1 2 3 4 5)
+          (-take 0 '(1 2 3 4 5))
+              ⇒ ()
+
+ -- Function: -take-last (n list)
+     Return a copy of the last N items of LIST in order.  Return a copy
+     of LIST if it contains N items or fewer.  Return ‘nil’ if N is zero
+     or less.
+
+     See also: ‘-take’ (*note -take::).
+
+          (-take-last 3 '(1 2 3 4 5))
+              ⇒ (3 4 5)
+          (-take-last 17 '(1 2 3 4 5))
+              ⇒ (1 2 3 4 5)
+          (-take-last 1 '(1 2 3 4 5))
+              ⇒ (5)
+
+ -- Function: -drop (n list)
+     Return the tail (not a copy) of LIST without the first N items.
+     Return ‘nil’ if LIST contains N items or fewer.  Return LIST if N
+     is zero or less.
+
+     For another variant, see also ‘-drop-last’ (*note -drop-last::).
+
+          (-drop 3 '(1 2 3 4 5))
+              ⇒ (4 5)
+          (-drop 17 '(1 2 3 4 5))
+              ⇒ ()
+          (-drop 0 '(1 2 3 4 5))
+              ⇒ (1 2 3 4 5)
+
+ -- Function: -drop-last (n list)
+     Return a copy of LIST without its last N items.  Return a copy of
+     LIST if N is zero or less.  Return ‘nil’ if LIST contains N items
+     or fewer.
+
+     See also: ‘-drop’ (*note -drop::).
+
+          (-drop-last 3 '(1 2 3 4 5))
+              ⇒ (1 2)
+          (-drop-last 17 '(1 2 3 4 5))
+              ⇒ ()
+          (-drop-last 0 '(1 2 3 4 5))
+              ⇒ (1 2 3 4 5)
+
+ -- Function: -take-while (pred list)
+     Take successive items from LIST for which PRED returns non-‘nil’.
+     PRED is a function of one argument.  Return a new list of the
+     successive elements from the start of LIST for which PRED returns
+     non-‘nil’.
+
+     This function’s anaphoric counterpart is ‘--take-while’.
+
+     For another variant, see also ‘-drop-while’ (*note -drop-while::).
+
+          (-take-while #'even? '(1 2 3 4))
+              ⇒ ()
+          (-take-while #'even? '(2 4 5 6))
+              ⇒ (2 4)
+          (--take-while (< it 4) '(1 2 3 4 3 2 1))
+              ⇒ (1 2 3)
+
+ -- Function: -drop-while (pred list)
+     Drop successive items from LIST for which PRED returns non-‘nil’.
+     PRED is a function of one argument.  Return the tail (not a copy)
+     of LIST starting from its first element for which PRED returns
+     ‘nil’.
+
+     This function’s anaphoric counterpart is ‘--drop-while’.
+
+     For another variant, see also ‘-take-while’ (*note -take-while::).
+
+          (-drop-while #'even? '(1 2 3 4))
+              ⇒ (1 2 3 4)
+          (-drop-while #'even? '(2 4 5 6))
+              ⇒ (5 6)
+          (--drop-while (< it 4) '(1 2 3 4 3 2 1))
+              ⇒ (4 3 2 1)
+
+ -- Function: -select-by-indices (indices list)
+     Return a list whose elements are elements from LIST selected as
+     ‘(nth i list)‘ for all i from INDICES.
+
+          (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r"))
+              ⇒ ("c" "o" "l" "o" "r")
+          (-select-by-indices '(2 1 0) '("a" "b" "c"))
+              ⇒ ("c" "b" "a")
+          (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l"))
+              ⇒ ("f" "a" "r" "f" "a" "l" "l" "a")
+
+ -- Function: -select-columns (columns table)
+     Select COLUMNS from TABLE.
+
+     TABLE is a list of lists where each element represents one row.  It
+     is assumed each row has the same length.
+
+     Each row is transformed such that only the specified COLUMNS are
+     selected.
+
+     See also: ‘-select-column’ (*note -select-column::),
+     ‘-select-by-indices’ (*note -select-by-indices::)
+
+          (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c)))
+              ⇒ ((1 3) (a c) (:a :c))
+          (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c)))
+              ⇒ ((2) (b) (:b))
+          (-select-columns nil '((1 2 3) (a b c) (:a :b :c)))
+              ⇒ (nil nil nil)
+
+ -- Function: -select-column (column table)
+     Select COLUMN from TABLE.
+
+     TABLE is a list of lists where each element represents one row.  It
+     is assumed each row has the same length.
+
+     The single selected column is returned as a list.
+
+     See also: ‘-select-columns’ (*note -select-columns::),
+     ‘-select-by-indices’ (*note -select-by-indices::)
+
+          (-select-column 1 '((1 2 3) (a b c) (:a :b :c)))
+              ⇒ (2 b :b)
+
+\1f
+File: dash.info,  Node: List to list,  Next: Reductions,  Prev: Sublist selection,  Up: Functions
+
+2.3 List to list
+================
+
+Functions returning a modified copy of the input list.
+
+ -- Function: -keep (fn list)
+     Return a new list of the non-‘nil’ results of applying FN to each
+     item in LIST.  Like ‘-filter’ (*note -filter::), but returns the
+     non-‘nil’ results of FN instead of the corresponding elements of
+     LIST.
+
+     Its anaphoric counterpart is ‘--keep’.
+
+          (-keep #'cdr '((1 2 3) (4 5) (6)))
+              ⇒ ((2 3) (5))
+          (-keep (lambda (n) (and (> n 3) (* 10 n))) '(1 2 3 4 5 6))
+              ⇒ (40 50 60)
+          (--keep (and (> it 3) (* 10 it)) '(1 2 3 4 5 6))
+              ⇒ (40 50 60)
+
+ -- Function: -concat (&rest sequences)
+     Concatenate all SEQUENCES and make the result a list.  The result
+     is a list whose elements are the elements of all the arguments.
+     Each argument may be a list, vector or string.
+
+     All arguments except the last argument are copied.  The last
+     argument is just used as the tail of the new list.  If the last
+     argument is not a list, this results in a dotted list.
+
+     As an exception, if all the arguments except the last are ‘nil’,
+     and the last argument is not a list, the return value is that last
+     argument unaltered, not a list.
+
+          (-concat '(1))
+              ⇒ (1)
+          (-concat '(1) '(2))
+              ⇒ (1 2)
+          (-concat '(1) '(2 3) '(4))
+              ⇒ (1 2 3 4)
+
+ -- Function: -flatten (l)
+     Take a nested list L and return its contents as a single, flat
+     list.
+
+     Note that because ‘nil’ represents a list of zero elements (an
+     empty list), any mention of ‘nil’ in L will disappear after
+     flattening.  If you need to preserve nils, consider ‘-flatten-n’
+     (*note -flatten-n::) or map them to some unique symbol and then map
+     them back.
+
+     Conses of two atoms are considered "terminals", that is, they
+     aren’t flattened further.
+
+     See also: ‘-flatten-n’ (*note -flatten-n::)
+
+          (-flatten '((1)))
+              ⇒ (1)
+          (-flatten '((1 (2 3) (((4 (5)))))))
+              ⇒ (1 2 3 4 5)
+          (-flatten '(1 2 (3 . 4)))
+              ⇒ (1 2 (3 . 4))
+
+ -- Function: -flatten-n (num list)
+     Flatten NUM levels of a nested LIST.
+
+     See also: ‘-flatten’ (*note -flatten::)
+
+          (-flatten-n 1 '((1 2) ((3 4) ((5 6)))))
+              ⇒ (1 2 (3 4) ((5 6)))
+          (-flatten-n 2 '((1 2) ((3 4) ((5 6)))))
+              ⇒ (1 2 3 4 (5 6))
+          (-flatten-n 3 '((1 2) ((3 4) ((5 6)))))
+              ⇒ (1 2 3 4 5 6)
+
+ -- Function: -replace (old new list)
+     Replace all OLD items in LIST with NEW.
+
+     Elements are compared using ‘equal’.
+
+     See also: ‘-replace-at’ (*note -replace-at::)
+
+          (-replace 1 "1" '(1 2 3 4 3 2 1))
+              ⇒ ("1" 2 3 4 3 2 "1")
+          (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
+              ⇒ ("a" "nice" "bar" "sentence" "about" "bar")
+          (-replace 1 2 nil)
+              ⇒ nil
+
+ -- Function: -replace-first (old new list)
+     Replace the first occurrence of OLD with NEW in LIST.
+
+     Elements are compared using ‘equal’.
+
+     See also: ‘-map-first’ (*note -map-first::)
+
+          (-replace-first 1 "1" '(1 2 3 4 3 2 1))
+              ⇒ ("1" 2 3 4 3 2 1)
+          (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
+              ⇒ ("a" "nice" "bar" "sentence" "about" "foo")
+          (-replace-first 1 2 nil)
+              ⇒ nil
+
+ -- Function: -replace-last (old new list)
+     Replace the last occurrence of OLD with NEW in LIST.
+
+     Elements are compared using ‘equal’.
+
+     See also: ‘-map-last’ (*note -map-last::)
+
+          (-replace-last 1 "1" '(1 2 3 4 3 2 1))
+              ⇒ (1 2 3 4 3 2 "1")
+          (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo"))
+              ⇒ ("a" "nice" "foo" "sentence" "about" "bar")
+          (-replace-last 1 2 nil)
+              ⇒ nil
+
+ -- Function: -insert-at (n x list)
+     Return a list with X inserted into LIST at position N.
+
+     See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note
+     -splice-list::)
+
+          (-insert-at 1 'x '(a b c))
+              ⇒ (a x b c)
+          (-insert-at 12 'x '(a b c))
+              ⇒ (a b c x)
+
+ -- Function: -replace-at (n x list)
+     Return a list with element at Nth position in LIST replaced with X.
+
+     See also: ‘-replace’ (*note -replace::)
+
+          (-replace-at 0 9 '(0 1 2 3 4 5))
+              ⇒ (9 1 2 3 4 5)
+          (-replace-at 1 9 '(0 1 2 3 4 5))
+              ⇒ (0 9 2 3 4 5)
+          (-replace-at 4 9 '(0 1 2 3 4 5))
+              ⇒ (0 1 2 3 9 5)
+
+ -- Function: -update-at (n func list)
+     Use FUNC to update the Nth element of LIST.  Return a copy of LIST
+     where the Nth element is replaced with the result of calling FUNC
+     on it.
+
+     See also: ‘-map-when’ (*note -map-when::)
+
+          (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5))
+              ⇒ (9 1 2 3 4 5)
+          (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5))
+              ⇒ (0 9 2 3 4 5)
+          (--update-at 2 (length it) '("foo" "bar" "baz" "quux"))
+              ⇒ ("foo" "bar" 3 "quux")
+
+ -- Function: -remove-at (n list)
+     Return LIST with its element at index N removed.  That is, remove
+     any element selected as (nth N LIST) from LIST and return the
+     result.
+
+     This is a non-destructive operation: parts of LIST (but not
+     necessarily all of it) are copied as needed to avoid destructively
+     modifying it.
+
+     See also: ‘-remove-at-indices’ (*note -remove-at-indices::),
+     ‘-remove’ (*note -remove::).
+
+          (-remove-at 0 '(a b c))
+              ⇒ (b c)
+          (-remove-at 1 '(a b c))
+              ⇒ (a c)
+          (-remove-at 2 '(a b c))
+              ⇒ (a b)
+
+ -- Function: -remove-at-indices (indices list)
+     Return LIST with its elements at INDICES removed.  That is, for
+     each index I in INDICES, remove any element selected as (nth I
+     LIST) from LIST.
+
+     This is a non-destructive operation: parts of LIST (but not
+     necessarily all of it) are copied as needed to avoid destructively
+     modifying it.
+
+     See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note
+     -remove::).
+
+          (-remove-at-indices '(0) '(a b c d e))
+              ⇒ (b c d e)
+          (-remove-at-indices '(1 3) '(a b c d e))
+              ⇒ (a c e)
+          (-remove-at-indices '(4 0 2) '(a b c d e))
+              ⇒ (b d)
+
+\1f
+File: dash.info,  Node: Reductions,  Next: Unfolding,  Prev: List to list,  Up: Functions
+
+2.4 Reductions
+==============
+
+Functions reducing lists to a single value (which may also be a list).
+
+ -- Function: -reduce-from (fn init list)
+     Reduce the function FN across LIST, starting with INIT.  Return the
+     result of applying FN to INIT and the first element of LIST, then
+     applying FN to that result and the second element, etc.  If LIST is
+     empty, return INIT without calling FN.
+
+     This function’s anaphoric counterpart is ‘--reduce-from’.
+
+     For other folds, see also ‘-reduce’ (*note -reduce::) and
+     ‘-reduce-r’ (*note -reduce-r::).
+
+          (-reduce-from #'- 10 '(1 2 3))
+              ⇒ 4
+          (-reduce-from #'list 10 '(1 2 3))
+              ⇒ (((10 1) 2) 3)
+          (--reduce-from (concat acc " " it) "START" '("a" "b" "c"))
+              ⇒ "START a b c"
+
+ -- Function: -reduce-r-from (fn init list)
+     Reduce the function FN across LIST in reverse, starting with INIT.
+     Return the result of applying FN to the last element of LIST and
+     INIT, then applying FN to the second-to-last element and the
+     previous result of FN, etc.  That is, the first argument of FN is
+     the current element, and its second argument the accumulated value.
+     If LIST is empty, return INIT without calling FN.
+
+     This function is like ‘-reduce-from’ (*note -reduce-from::) but the
+     operation associates from the right rather than left.  In other
+     words, it starts from the end of LIST and flips the arguments to
+     FN.  Conceptually, it is like replacing the conses in LIST with
+     applications of FN, and its last link with INIT, and evaluating the
+     resulting expression.
+
+     This function’s anaphoric counterpart is ‘--reduce-r-from’.
+
+     For other folds, see also ‘-reduce-r’ (*note -reduce-r::) and
+     ‘-reduce’ (*note -reduce::).
+
+          (-reduce-r-from #'- 10 '(1 2 3))
+              ⇒ -8
+          (-reduce-r-from #'list 10 '(1 2 3))
+              ⇒ (1 (2 (3 10)))
+          (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c"))
+              ⇒ "a b c END"
+
+ -- Function: -reduce (fn list)
+     Reduce the function FN across LIST.  Return the result of applying
+     FN to the first two elements of LIST, then applying FN to that
+     result and the third element, etc.  If LIST contains a single
+     element, return it without calling FN.  If LIST is empty, return
+     the result of calling FN with no arguments.
+
+     This function’s anaphoric counterpart is ‘--reduce’.
+
+     For other folds, see also ‘-reduce-from’ (*note -reduce-from::) and
+     ‘-reduce-r’ (*note -reduce-r::).
+
+          (-reduce #'- '(1 2 3 4))
+              ⇒ -8
+          (-reduce #'list '(1 2 3 4))
+              ⇒ (((1 2) 3) 4)
+          (--reduce (format "%s-%d" acc it) '(1 2 3))
+              ⇒ "1-2-3"
+
+ -- Function: -reduce-r (fn list)
+     Reduce the function FN across LIST in reverse.  Return the result
+     of applying FN to the last two elements of LIST, then applying FN
+     to the third-to-last element and the previous result of FN, etc.
+     That is, the first argument of FN is the current element, and its
+     second argument the accumulated value.  If LIST contains a single
+     element, return it without calling FN.  If LIST is empty, return
+     the result of calling FN with no arguments.
+
+     This function is like ‘-reduce’ (*note -reduce::) but the operation
+     associates from the right rather than left.  In other words, it
+     starts from the end of LIST and flips the arguments to FN.
+     Conceptually, it is like replacing the conses in LIST with
+     applications of FN, ignoring its last link, and evaluating the
+     resulting expression.
+
+     This function’s anaphoric counterpart is ‘--reduce-r’.
+
+     For other folds, see also ‘-reduce-r-from’ (*note -reduce-r-from::)
+     and ‘-reduce’ (*note -reduce::).
+
+          (-reduce-r #'- '(1 2 3 4))
+              ⇒ -2
+          (-reduce-r #'list '(1 2 3 4))
+              ⇒ (1 (2 (3 4)))
+          (--reduce-r (format "%s-%d" acc it) '(1 2 3))
+              ⇒ "3-2-1"
+
+ -- Function: -reductions-from (fn init list)
+     Return a list of FN’s intermediate reductions across LIST.  That
+     is, a list of the intermediate values of the accumulator when
+     ‘-reduce-from’ (*note -reduce-from::) (which see) is called with
+     the same arguments.
+
+     This function’s anaphoric counterpart is ‘--reductions-from’.
+
+     For other folds, see also ‘-reductions’ (*note -reductions::) and
+     ‘-reductions-r’ (*note -reductions-r::).
+
+          (-reductions-from #'max 0 '(2 1 4 3))
+              ⇒ (0 2 2 4 4)
+          (-reductions-from #'* 1 '(1 2 3 4))
+              ⇒ (1 1 2 6 24)
+          (--reductions-from (format "(FN %s %d)" acc it) "INIT" '(1 2 3))
+              ⇒ ("INIT" "(FN INIT 1)" "(FN (FN INIT 1) 2)" "(FN (FN (FN INIT 1) 2) 3)")
+
+ -- Function: -reductions-r-from (fn init list)
+     Return a list of FN’s intermediate reductions across reversed LIST.
+     That is, a list of the intermediate values of the accumulator when
+     ‘-reduce-r-from’ (*note -reduce-r-from::) (which see) is called
+     with the same arguments.
+
+     This function’s anaphoric counterpart is ‘--reductions-r-from’.
+
+     For other folds, see also ‘-reductions’ (*note -reductions::) and
+     ‘-reductions-r’ (*note -reductions-r::).
+
+          (-reductions-r-from #'max 0 '(2 1 4 3))
+              ⇒ (4 4 4 3 0)
+          (-reductions-r-from #'* 1 '(1 2 3 4))
+              ⇒ (24 24 12 4 1)
+          (--reductions-r-from (format "(FN %d %s)" it acc) "INIT" '(1 2 3))
+              ⇒ ("(FN 1 (FN 2 (FN 3 INIT)))" "(FN 2 (FN 3 INIT))" "(FN 3 INIT)" "INIT")
+
+ -- Function: -reductions (fn list)
+     Return a list of FN’s intermediate reductions across LIST.  That
+     is, a list of the intermediate values of the accumulator when
+     ‘-reduce’ (*note -reduce::) (which see) is called with the same
+     arguments.
+
+     This function’s anaphoric counterpart is ‘--reductions’.
+
+     For other folds, see also ‘-reductions’ (*note -reductions::) and
+     ‘-reductions-r’ (*note -reductions-r::).
+
+          (-reductions #'+ '(1 2 3 4))
+              ⇒ (1 3 6 10)
+          (-reductions #'* '(1 2 3 4))
+              ⇒ (1 2 6 24)
+          (--reductions (format "(FN %s %d)" acc it) '(1 2 3))
+              ⇒ (1 "(FN 1 2)" "(FN (FN 1 2) 3)")
+
+ -- Function: -reductions-r (fn list)
+     Return a list of FN’s intermediate reductions across reversed LIST.
+     That is, a list of the intermediate values of the accumulator when
+     ‘-reduce-r’ (*note -reduce-r::) (which see) is called with the same
+     arguments.
+
+     This function’s anaphoric counterpart is ‘--reductions-r’.
+
+     For other folds, see also ‘-reductions-r-from’ (*note
+     -reductions-r-from::) and ‘-reductions’ (*note -reductions::).
+
+          (-reductions-r #'+ '(1 2 3 4))
+              ⇒ (10 9 7 4)
+          (-reductions-r #'* '(1 2 3 4))
+              ⇒ (24 24 12 4)
+          (--reductions-r (format "(FN %d %s)" it acc) '(1 2 3))
+              ⇒ ("(FN 1 (FN 2 3))" "(FN 2 3)" 3)
+
+ -- Function: -count (pred list)
+     Counts the number of items in LIST where (PRED item) is non-‘nil’.
+
+          (-count 'even? '(1 2 3 4 5))
+              ⇒ 2
+          (--count (< it 4) '(1 2 3 4))
+              ⇒ 3
+
+ -- Function: -sum (list)
+     Return the sum of LIST.
+
+          (-sum ())
+              ⇒ 0
+          (-sum '(1))
+              ⇒ 1
+          (-sum '(1 2 3 4))
+              ⇒ 10
+
+ -- Function: -running-sum (list)
+     Return a list with running sums of items in LIST.  LIST must be
+     non-empty.
+
+          (-running-sum '(1 2 3 4))
+              ⇒ (1 3 6 10)
+          (-running-sum '(1))
+              ⇒ (1)
+          (-running-sum ())
+              error→ Wrong type argument: consp, nil
+
+ -- Function: -product (list)
+     Return the product of LIST.
+
+          (-product ())
+              ⇒ 1
+          (-product '(1))
+              ⇒ 1
+          (-product '(1 2 3 4))
+              ⇒ 24
+
+ -- Function: -running-product (list)
+     Return a list with running products of items in LIST.  LIST must be
+     non-empty.
+
+          (-running-product '(1 2 3 4))
+              ⇒ (1 2 6 24)
+          (-running-product '(1))
+              ⇒ (1)
+          (-running-product ())
+              error→ Wrong type argument: consp, nil
+
+ -- Function: -inits (list)
+     Return all prefixes of LIST.
+
+          (-inits '(1 2 3 4))
+              ⇒ (nil (1) (1 2) (1 2 3) (1 2 3 4))
+          (-inits nil)
+              ⇒ (nil)
+          (-inits '(1))
+              ⇒ (nil (1))
+
+ -- Function: -tails (list)
+     Return all suffixes of LIST.
+
+          (-tails '(1 2 3 4))
+              ⇒ ((1 2 3 4) (2 3 4) (3 4) (4) nil)
+          (-tails nil)
+              ⇒ (nil)
+          (-tails '(1))
+              ⇒ ((1) nil)
+
+ -- Function: -common-prefix (&rest lists)
+     Return the longest common prefix of LISTS.
+
+          (-common-prefix '(1))
+              ⇒ (1)
+          (-common-prefix '(1 2) '(3 4) '(1 2))
+              ⇒ ()
+          (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4))
+              ⇒ (1 2)
+
+ -- Function: -common-suffix (&rest lists)
+     Return the longest common suffix of LISTS.
+
+          (-common-suffix '(1))
+              ⇒ (1)
+          (-common-suffix '(1 2) '(3 4) '(1 2))
+              ⇒ ()
+          (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4))
+              ⇒ (3 4)
+
+ -- Function: -min (list)
+     Return the smallest value from LIST of numbers or markers.
+
+          (-min '(0))
+              ⇒ 0
+          (-min '(3 2 1))
+              ⇒ 1
+          (-min '(1 2 3))
+              ⇒ 1
+
+ -- Function: -min-by (comparator list)
+     Take a comparison function COMPARATOR and a LIST and return the
+     least element of the list by the comparison function.
+
+     See also combinator ‘-on’ (*note -on::) which can transform the
+     values before comparing them.
+
+          (-min-by '> '(4 3 6 1))
+              ⇒ 1
+          (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2)))
+              ⇒ (1 2 3)
+          (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2)))
+              ⇒ (2)
+
+ -- Function: -max (list)
+     Return the largest value from LIST of numbers or markers.
+
+          (-max '(0))
+              ⇒ 0
+          (-max '(3 2 1))
+              ⇒ 3
+          (-max '(1 2 3))
+              ⇒ 3
+
+ -- Function: -max-by (comparator list)
+     Take a comparison function COMPARATOR and a LIST and return the
+     greatest element of the list by the comparison function.
+
+     See also combinator ‘-on’ (*note -on::) which can transform the
+     values before comparing them.
+
+          (-max-by '> '(4 3 6 1))
+              ⇒ 6
+          (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2)))
+              ⇒ (3 2)
+          (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2)))
+              ⇒ (1 2 3)
+
+ -- Function: -frequencies (list)
+     Count the occurrences of each distinct element of LIST.
+
+     Return an alist of (ELEMENT .  N), where each ELEMENT occurs N
+     times in LIST.
+
+     The test for equality is done with ‘equal’, or with ‘-compare-fn’
+     if that is non-‘nil’.
+
+     See also ‘-count’ (*note -count::) and ‘-group-by’ (*note
+     -group-by::).
+
+          (-frequencies ())
+              ⇒ ()
+          (-frequencies '(1 2 3 1 2 1))
+              ⇒ ((1 . 3) (2 . 2) (3 . 1))
+          (let ((-compare-fn #'string=)) (-frequencies '(a "a")))
+              ⇒ ((a . 2))
+
+\1f
+File: dash.info,  Node: Unfolding,  Next: Predicates,  Prev: Reductions,  Up: Functions
+
+2.5 Unfolding
+=============
+
+Operations dual to reductions, building lists from a seed value rather
+than consuming a list to produce a single value.
+
+ -- Function: -iterate (fun init n)
+     Return a list of iterated applications of FUN to INIT.
+
+     This means a list of the form:
+
+     (INIT (FUN INIT) (FUN (FUN INIT)) ...)
+
+     N is the length of the returned list.
+
+          (-iterate #'1+ 1 10)
+              ⇒ (1 2 3 4 5 6 7 8 9 10)
+          (-iterate (lambda (x) (+ x x)) 2 5)
+              ⇒ (2 4 8 16 32)
+          (--iterate (* it it) 2 5)
+              ⇒ (2 4 16 256 65536)
+
+ -- Function: -unfold (fun seed)
+     Build a list from SEED using FUN.
+
+     This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while
+     -reduce-r consumes a list to produce a single value, ‘-unfold’
+     (*note -unfold::) takes a seed value and builds a (potentially
+     infinite!)  list.
+
+     FUN should return ‘nil’ to stop the generating process, or a cons
+     (A .  B), where A will be prepended to the result and B is the new
+     seed.
+
+          (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10)
+              ⇒ (10 9 8 7 6 5 4 3 2 1)
+          (--unfold (when it (cons it (cdr it))) '(1 2 3 4))
+              ⇒ ((1 2 3 4) (2 3 4) (3 4) (4))
+          (--unfold (when it (cons it (butlast it))) '(1 2 3 4))
+              ⇒ ((1 2 3 4) (1 2 3) (1 2) (1))
+
+ -- Function: -repeat (n x)
+     Return a new list of length N with each element being X.  Return
+     ‘nil’ if N is less than 1.
+
+          (-repeat 3 :a)
+              ⇒ (:a :a :a)
+          (-repeat 1 :a)
+              ⇒ (:a)
+          (-repeat 0 :a)
+              ⇒ ()
+
+ -- Function: -cycle (list)
+     Return an infinite circular copy of LIST.  The returned list cycles
+     through the elements of LIST and repeats from the beginning.
+
+          (-take 5 (-cycle '(1 2 3)))
+              ⇒ (1 2 3 1 2)
+          (-take 7 (-cycle '(1 "and" 3)))
+              ⇒ (1 "and" 3 1 "and" 3 1)
+          (-zip-lists (-cycle '(3)) '(1 2))
+              ⇒ ((3 1) (3 2))
+
+\1f
+File: dash.info,  Node: Predicates,  Next: Partitioning,  Prev: Unfolding,  Up: Functions
+
+2.6 Predicates
+==============
+
+Reductions of one or more lists to a boolean value.
+
+ -- Function: -some (pred list)
+     Return (PRED x) for the first LIST item where (PRED x) is
+     non-‘nil’, else ‘nil’.
+
+     Alias: ‘-any’.
+
+     This function’s anaphoric counterpart is ‘--some’.
+
+          (-some #'stringp '(1 "2" 3))
+              ⇒ t
+          (--some (string-match-p "x" it) '("foo" "axe" "xor"))
+              ⇒ 1
+          (--some (= it-index 3) '(0 1 2))
+              ⇒ nil
+
+ -- Function: -every (pred list)
+     Return non-‘nil’ if PRED returns non-‘nil’ for all items in LIST.
+     If so, return the last such result of PRED.  Otherwise, once an
+     item is reached for which PRED returns ‘nil’, return ‘nil’ without
+     calling PRED on any further LIST elements.
+
+     This function is like ‘-every-p’, but on success returns the last
+     non-‘nil’ result of PRED instead of just ‘t’.
+
+     This function’s anaphoric counterpart is ‘--every’.
+
+          (-every #'numberp '(1 2 3))
+              ⇒ t
+          (--every (string-match-p "x" it) '("axe" "xor"))
+              ⇒ 0
+          (--every (= it it-index) '(0 1 3))
+              ⇒ nil
+
+ -- Function: -any? (pred list)
+     Return ‘t’ if (PRED X) is non-‘nil’ for any X in LIST, else ‘nil’.
+
+     Alias: ‘-any-p’, ‘-some?’, ‘-some-p’
+
+          (-any? #'numberp '(nil 0 t))
+              ⇒ t
+          (-any? #'numberp '(nil t t))
+              ⇒ nil
+          (-any? #'null '(1 3 5))
+              ⇒ nil
+
+ -- Function: -all? (pred list)
+     Return ‘t’ if (PRED X) is non-‘nil’ for all X in LIST, else ‘nil’.
+     In the latter case, stop after the first X for which (PRED X) is
+     ‘nil’, without calling PRED on any subsequent elements of LIST.
+
+     The similar function ‘-every’ (*note -every::) is more widely
+     useful, since it returns the last non-‘nil’ result of PRED instead
+     of just ‘t’ on success.
+
+     Alias: ‘-all-p’, ‘-every-p’, ‘-every?’.
+
+     This function’s anaphoric counterpart is ‘--all?’.
+
+          (-all? #'numberp '(1 2 3))
+              ⇒ t
+          (-all? #'numberp '(2 t 6))
+              ⇒ nil
+          (--all? (= 0 (% it 2)) '(2 4 6))
+              ⇒ t
+
+ -- Function: -none? (pred list)
+     Return ‘t’ if (PRED X) is ‘nil’ for all X in LIST, else ‘nil’.
+
+     Alias: ‘-none-p’
+
+          (-none? 'even? '(1 2 3))
+              ⇒ nil
+          (-none? 'even? '(1 3 5))
+              ⇒ t
+          (--none? (= 0 (% it 2)) '(1 2 3))
+              ⇒ nil
+
+ -- Function: -only-some? (pred list)
+     Return ‘t’ if different LIST items both satisfy and do not satisfy
+     PRED.  That is, if PRED returns both ‘nil’ for at least one item,
+     and non-‘nil’ for at least one other item in LIST.  Return ‘nil’ if
+     all items satisfy the predicate or none of them do.
+
+     Alias: ‘-only-some-p’
+
+          (-only-some? 'even? '(1 2 3))
+              ⇒ t
+          (-only-some? 'even? '(1 3 5))
+              ⇒ nil
+          (-only-some? 'even? '(2 4 6))
+              ⇒ nil
+
+ -- Function: -contains? (list element)
+     Return non-‘nil’ if LIST contains ELEMENT.
+
+     The test for equality is done with ‘equal’, or with ‘-compare-fn’
+     if that is non-‘nil’.  As with ‘member’, the return value is
+     actually the tail of LIST whose car is ELEMENT.
+
+     Alias: ‘-contains-p’.
+
+          (-contains? '(1 2 3) 1)
+              ⇒ (1 2 3)
+          (-contains? '(1 2 3) 2)
+              ⇒ (2 3)
+          (-contains? '(1 2 3) 4)
+              ⇒ ()
+
+ -- Function: -is-prefix? (prefix list)
+     Return non-‘nil’ if PREFIX is a prefix of LIST.
+
+     Alias: ‘-is-prefix-p’.
+
+          (-is-prefix? '(1 2 3) '(1 2 3 4 5))
+              ⇒ t
+          (-is-prefix? '(1 2 3 4 5) '(1 2 3))
+              ⇒ nil
+          (-is-prefix? '(1 3) '(1 2 3 4 5))
+              ⇒ nil
+
+ -- Function: -is-suffix? (suffix list)
+     Return non-‘nil’ if SUFFIX is a suffix of LIST.
+
+     Alias: ‘-is-suffix-p’.
+
+          (-is-suffix? '(3 4 5) '(1 2 3 4 5))
+              ⇒ t
+          (-is-suffix? '(1 2 3 4 5) '(3 4 5))
+              ⇒ nil
+          (-is-suffix? '(3 5) '(1 2 3 4 5))
+              ⇒ nil
+
+ -- Function: -is-infix? (infix list)
+     Return non-‘nil’ if INFIX is infix of LIST.
+
+     This operation runs in O(n^2) time
+
+     Alias: ‘-is-infix-p’
+
+          (-is-infix? '(1 2 3) '(1 2 3 4 5))
+              ⇒ t
+          (-is-infix? '(2 3 4) '(1 2 3 4 5))
+              ⇒ t
+          (-is-infix? '(3 4 5) '(1 2 3 4 5))
+              ⇒ t
+
+ -- Function: -cons-pair? (obj)
+     Return non-‘nil’ if OBJ is a true cons pair.  That is, a cons (A .
+     B) where B is not a list.
+
+     Alias: ‘-cons-pair-p’.
+
+          (-cons-pair? '(1 . 2))
+              ⇒ t
+          (-cons-pair? '(1 2))
+              ⇒ nil
+          (-cons-pair? '(1))
+              ⇒ nil
+
+\1f
+File: dash.info,  Node: Partitioning,  Next: Indexing,  Prev: Predicates,  Up: Functions
+
+2.7 Partitioning
+================
+
+Functions partitioning the input list into a list of lists.
+
+ -- Function: -split-at (n list)
+     Split LIST into two sublists after the Nth element.  The result is
+     a list of two elements (TAKE DROP) where TAKE is a new list of the
+     first N elements of LIST, and DROP is the remaining elements of
+     LIST (not a copy).  TAKE and DROP are like the results of ‘-take’
+     (*note -take::) and ‘-drop’ (*note -drop::), respectively, but the
+     split is done in a single list traversal.
+
+          (-split-at 3 '(1 2 3 4 5))
+              ⇒ ((1 2 3) (4 5))
+          (-split-at 17 '(1 2 3 4 5))
+              ⇒ ((1 2 3 4 5) nil)
+          (-split-at 0 '(1 2 3 4 5))
+              ⇒ (nil (1 2 3 4 5))
+
+ -- Function: -split-with (pred list)
+     Split LIST into a prefix satisfying PRED, and the rest.  The first
+     sublist is the prefix of LIST with successive elements satisfying
+     PRED, and the second sublist is the remaining elements that do not.
+     The result is like performing
+
+     ((-take-while PRED LIST) (-drop-while PRED LIST))
+
+     but in no more than a single pass through LIST.
+
+          (-split-with 'even? '(1 2 3 4))
+              ⇒ (nil (1 2 3 4))
+          (-split-with 'even? '(2 4 5 6))
+              ⇒ ((2 4) (5 6))
+          (--split-with (< it 4) '(1 2 3 4 3 2 1))
+              ⇒ ((1 2 3) (4 3 2 1))
+
+ -- Macro: -split-on (item list)
+     Split the LIST each time ITEM is found.
+
+     Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is
+     discarded from the results.  Empty lists are also removed from the
+     result.
+
+     Comparison is done by ‘equal’.
+
+     See also ‘-split-when’ (*note -split-when::)
+
+          (-split-on '| '(Nil | Leaf a | Node [Tree a]))
+              ⇒ ((Nil) (Leaf a) (Node [Tree a]))
+          (-split-on :endgroup '("a" "b" :endgroup "c" :endgroup "d" "e"))
+              ⇒ (("a" "b") ("c") ("d" "e"))
+          (-split-on :endgroup '("a" "b" :endgroup :endgroup "d" "e"))
+              ⇒ (("a" "b") ("d" "e"))
+
+ -- Function: -split-when (fn list)
+     Split the LIST on each element where FN returns non-‘nil’.
+
+     Unlike ‘-partition-by’ (*note -partition-by::), the "matched"
+     element is discarded from the results.  Empty lists are also
+     removed from the result.
+
+     This function can be thought of as a generalization of
+     ‘split-string’.
+
+          (-split-when 'even? '(1 2 3 4 5 6))
+              ⇒ ((1) (3) (5))
+          (-split-when 'even? '(1 2 3 4 6 8 9))
+              ⇒ ((1) (3) (9))
+          (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args))
+              ⇒ ((a b) (c d) (args))
+
+ -- Function: -separate (pred list)
+     Split LIST into two sublists based on whether items satisfy PRED.
+     The result is like performing
+
+     ((-filter PRED LIST) (-remove PRED LIST))
+
+     but in a single pass through LIST.
+
+          (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7))
+              ⇒ ((2 4 6) (1 3 5 7))
+          (--separate (< it 5) '(3 7 5 9 3 2 1 4 6))
+              ⇒ ((3 3 2 1 4) (7 5 9 6))
+          (-separate 'cdr '((1 2) (1) (1 2 3) (4)))
+              ⇒ (((1 2) (1 2 3)) ((1) (4)))
+
+ -- Function: -partition (n list)
+     Return a new list with the items in LIST grouped into N-sized
+     sublists.  If there are not enough items to make the last group
+     N-sized, those items are discarded.
+
+          (-partition 2 '(1 2 3 4 5 6))
+              ⇒ ((1 2) (3 4) (5 6))
+          (-partition 2 '(1 2 3 4 5 6 7))
+              ⇒ ((1 2) (3 4) (5 6))
+          (-partition 3 '(1 2 3 4 5 6 7))
+              ⇒ ((1 2 3) (4 5 6))
+
+ -- Function: -partition-all (n list)
+     Return a new list with the items in LIST grouped into N-sized
+     sublists.  The last group may contain less than N items.
+
+          (-partition-all 2 '(1 2 3 4 5 6))
+              ⇒ ((1 2) (3 4) (5 6))
+          (-partition-all 2 '(1 2 3 4 5 6 7))
+              ⇒ ((1 2) (3 4) (5 6) (7))
+          (-partition-all 3 '(1 2 3 4 5 6 7))
+              ⇒ ((1 2 3) (4 5 6) (7))
+
+ -- Function: -partition-in-steps (n step list)
+     Partition LIST into sublists of length N that are STEP items apart.
+     Like ‘-partition-all-in-steps’ (*note -partition-all-in-steps::),
+     but if there are not enough items to make the last group N-sized,
+     those items are discarded.
+
+          (-partition-in-steps 2 1 '(1 2 3 4))
+              ⇒ ((1 2) (2 3) (3 4))
+          (-partition-in-steps 3 2 '(1 2 3 4))
+              ⇒ ((1 2 3))
+          (-partition-in-steps 3 2 '(1 2 3 4 5))
+              ⇒ ((1 2 3) (3 4 5))
+
+ -- Function: -partition-all-in-steps (n step list)
+     Partition LIST into sublists of length N that are STEP items apart.
+     Adjacent groups may overlap if N exceeds the STEP stride.  Trailing
+     groups may contain less than N items.
+
+          (-partition-all-in-steps 2 1 '(1 2 3 4))
+              ⇒ ((1 2) (2 3) (3 4) (4))
+          (-partition-all-in-steps 3 2 '(1 2 3 4))
+              ⇒ ((1 2 3) (3 4))
+          (-partition-all-in-steps 3 2 '(1 2 3 4 5))
+              ⇒ ((1 2 3) (3 4 5) (5))
+
+ -- Function: -partition-by (fn list)
+     Apply FN to each item in LIST, splitting it each time FN returns a
+     new value.
+
+          (-partition-by 'even? ())
+              ⇒ ()
+          (-partition-by 'even? '(1 1 2 2 2 3 4 6 8))
+              ⇒ ((1 1) (2 2 2) (3) (4 6 8))
+          (--partition-by (< it 3) '(1 2 3 4 3 2 1))
+              ⇒ ((1 2) (3 4 3) (2 1))
+
+ -- Function: -partition-by-header (fn list)
+     Apply FN to the first item in LIST.  That is the header value.
+     Apply FN to each item in LIST, splitting it each time FN returns
+     the header value, but only after seeing at least one other value
+     (the body).
+
+          (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4))
+              ⇒ ((1 2 3) (1 2) (1 2 3 4))
+          (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0))
+              ⇒ ((1 2 0) (1 0) (1 2 3 0))
+          (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1))
+              ⇒ ((2 1 1 1) (4 1 3 5) (6 6 1))
+
+ -- Function: -partition-after-pred (pred list)
+     Partition LIST after each element for which PRED returns non-‘nil’.
+
+     This function’s anaphoric counterpart is ‘--partition-after-pred’.
+
+          (-partition-after-pred #'booleanp ())
+              ⇒ ()
+          (-partition-after-pred #'booleanp '(t t))
+              ⇒ ((t) (t))
+          (-partition-after-pred #'booleanp '(0 0 t t 0 t))
+              ⇒ ((0 0 t) (t) (0 t))
+
+ -- Function: -partition-before-pred (pred list)
+     Partition directly before each time PRED is true on an element of
+     LIST.
+
+          (-partition-before-pred #'booleanp ())
+              ⇒ ()
+          (-partition-before-pred #'booleanp '(0 t))
+              ⇒ ((0) (t))
+          (-partition-before-pred #'booleanp '(0 0 t 0 t t))
+              ⇒ ((0 0) (t 0) (t) (t))
+
+ -- Function: -partition-before-item (item list)
+     Partition directly before each time ITEM appears in LIST.
+
+          (-partition-before-item 3 ())
+              ⇒ ()
+          (-partition-before-item 3 '(1))
+              ⇒ ((1))
+          (-partition-before-item 3 '(3))
+              ⇒ ((3))
+
+ -- Function: -partition-after-item (item list)
+     Partition directly after each time ITEM appears in LIST.
+
+          (-partition-after-item 3 ())
+              ⇒ ()
+          (-partition-after-item 3 '(1))
+              ⇒ ((1))
+          (-partition-after-item 3 '(3))
+              ⇒ ((3))
+
+ -- Function: -group-by (fn list)
+     Separate LIST into an alist whose keys are FN applied to the
+     elements of LIST.  Keys are compared by ‘equal’.
+
+          (-group-by 'even? ())
+              ⇒ ()
+          (-group-by 'even? '(1 1 2 2 2 3 4 6 8))
+              ⇒ ((nil 1 1 3) (t 2 2 2 4 6 8))
+          (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e"))
+              ⇒ (("a" "a/b" "a/e") ("c" "c/d"))
+
+\1f
+File: dash.info,  Node: Indexing,  Next: Set operations,  Prev: Partitioning,  Up: Functions
+
+2.8 Indexing
+============
+
+Functions retrieving or sorting based on list indices and related
+predicates.
+
+ -- Function: -elem-index (elem list)
+     Return the first index of ELEM in LIST.  That is, the index within
+     LIST of the first element that is ‘equal’ to ELEM.  Return ‘nil’ if
+     there is no such element.
+
+     See also: ‘-find-index’ (*note -find-index::).
+
+          (-elem-index 2 '(6 7 8 3 4))
+              ⇒ nil
+          (-elem-index "bar" '("foo" "bar" "baz"))
+              ⇒ 1
+          (-elem-index '(1 2) '((3) (5 6) (1 2) nil))
+              ⇒ 2
+
+ -- Function: -elem-indices (elem list)
+     Return the list of indices at which ELEM appears in LIST.  That is,
+     the indices of all elements of LIST ‘equal’ to ELEM, in the same
+     ascending order as they appear in LIST.
+
+          (-elem-indices 2 '(6 7 8 3 4 1))
+              ⇒ ()
+          (-elem-indices "bar" '("foo" "bar" "baz"))
+              ⇒ (1)
+          (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil))
+              ⇒ (1 3)
+
+ -- Function: -find-index (pred list)
+     Return the index of the first item satisfying PRED in LIST.  Return
+     ‘nil’ if no such item is found.
+
+     PRED is called with one argument, the current list element, until
+     it returns non-‘nil’, at which point the search terminates.
+
+     This function’s anaphoric counterpart is ‘--find-index’.
+
+     See also: ‘-first’ (*note -first::), ‘-find-last-index’ (*note
+     -find-last-index::).
+
+          (-find-index #'numberp '(a b c))
+              ⇒ nil
+          (-find-index #'natnump '(1 0 -1))
+              ⇒ 0
+          (--find-index (> it 5) '(2 4 1 6 3 3 5 8))
+              ⇒ 3
+
+ -- Function: -find-last-index (pred list)
+     Return the index of the last item satisfying PRED in LIST.  Return
+     ‘nil’ if no such item is found.
+
+     Predicate PRED is called with one argument each time, namely the
+     current list element.
+
+     This function’s anaphoric counterpart is ‘--find-last-index’.
+
+     See also: ‘-last’ (*note -last::), ‘-find-index’ (*note
+     -find-index::).
+
+          (-find-last-index #'numberp '(a b c))
+              ⇒ nil
+          (--find-last-index (> it 5) '(2 7 1 6 3 8 5 2))
+              ⇒ 5
+          (-find-last-index (-partial #'string< 'a) '(c b a))
+              ⇒ 1
+
+ -- Function: -find-indices (pred list)
+     Return the list of indices in LIST satisfying PRED.
+
+     Each element of LIST in turn is passed to PRED.  If the result is
+     non-‘nil’, the index of that element in LIST is included in the
+     result.  The returned indices are in ascending order, i.e., in the
+     same order as they appear in LIST.
+
+     This function’s anaphoric counterpart is ‘--find-indices’.
+
+     See also: ‘-find-index’ (*note -find-index::), ‘-elem-indices’
+     (*note -elem-indices::).
+
+          (-find-indices #'numberp '(a b c))
+              ⇒ ()
+          (-find-indices #'numberp '(8 1 d 2 b c a 3))
+              ⇒ (0 1 3 7)
+          (--find-indices (> it 5) '(2 4 1 6 3 3 5 8))
+              ⇒ (3 7)
+
+ -- Function: -grade-up (comparator list)
+     Grade elements of LIST using COMPARATOR relation.  This yields a
+     permutation vector such that applying this permutation to LIST
+     sorts it in ascending order.
+
+          (-grade-up #'< '(3 1 4 2 1 3 3))
+              ⇒ (1 4 3 0 5 6 2)
+          (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up #'< l) l))
+              ⇒ (1 1 2 3 3 3 4)
+
+ -- Function: -grade-down (comparator list)
+     Grade elements of LIST using COMPARATOR relation.  This yields a
+     permutation vector such that applying this permutation to LIST
+     sorts it in descending order.
+
+          (-grade-down #'< '(3 1 4 2 1 3 3))
+              ⇒ (2 0 5 6 3 1 4)
+          (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down #'< l) l))
+              ⇒ (4 3 3 3 2 1 1)
+
+\1f
+File: dash.info,  Node: Set operations,  Next: Other list operations,  Prev: Indexing,  Up: Functions
+
+2.9 Set operations
+==================
+
+Operations pretending lists are sets.
+
+ -- Function: -union (list1 list2)
+     Return a new list of distinct elements appearing in either LIST1 or
+     LIST2.
+
+     The test for equality is done with ‘equal’, or with ‘-compare-fn’
+     if that is non-‘nil’.
+
+          (-union '(1 2 3) '(3 4 5))
+              ⇒ (1 2 3 4 5)
+          (-union '(1 2 2 4) ())
+              ⇒ (1 2 4)
+          (-union '(1 1 2 2) '(4 4 3 2 1))
+              ⇒ (1 2 4 3)
+
+ -- Function: -difference (list1 list2)
+     Return a new list with the distinct members of LIST1 that are not
+     in LIST2.
+
+     The test for equality is done with ‘equal’, or with ‘-compare-fn’
+     if that is non-‘nil’.
+
+          (-difference () ())
+              ⇒ ()
+          (-difference '(1 2 3) '(4 5 6))
+              ⇒ (1 2 3)
+          (-difference '(1 2 3 4) '(3 4 5 6))
+              ⇒ (1 2)
+
+ -- Function: -intersection (list1 list2)
+     Return a new list of distinct elements appearing in both LIST1 and
+     LIST2.
+
+     The test for equality is done with ‘equal’, or with ‘-compare-fn’
+     if that is non-‘nil’.
+
+          (-intersection () ())
+              ⇒ ()
+          (-intersection '(1 2 3) '(4 5 6))
+              ⇒ ()
+          (-intersection '(1 2 2 3) '(4 3 3 2))
+              ⇒ (2 3)
+
+ -- Function: -powerset (list)
+     Return the power set of LIST.
+
+          (-powerset ())
+              ⇒ (nil)
+          (-powerset '(x y))
+              ⇒ ((x y) (x) (y) nil)
+          (-powerset '(x y z))
+              ⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil)
+
+ -- Function: -permutations (list)
+     Return the distinct permutations of LIST.
+
+     Duplicate elements of LIST are determined by ‘equal’, or by
+     ‘-compare-fn’ if that is non-‘nil’.
+
+          (-permutations ())
+              ⇒ (nil)
+          (-permutations '(a a b))
+              ⇒ ((a a b) (a b a) (b a a))
+          (-permutations '(a b c))
+              ⇒ ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))
+
+ -- Function: -distinct (list)
+     Return a copy of LIST with all duplicate elements removed.
+
+     The test for equality is done with ‘equal’, or with ‘-compare-fn’
+     if that is non-‘nil’.
+
+     Alias: ‘-uniq’.
+
+          (-distinct ())
+              ⇒ ()
+          (-distinct '(1 1 2 3 3))
+              ⇒ (1 2 3)
+          (-distinct '(t t t))
+              ⇒ (t)
+
+ -- Function: -same-items? (list1 list2)
+     Return non-‘nil’ if LIST1 and LIST2 have the same distinct
+     elements.
+
+     The order of the elements in the lists does not matter.  The lists
+     may be of different lengths, i.e., contain duplicate elements.  The
+     test for equality is done with ‘equal’, or with ‘-compare-fn’ if
+     that is non-‘nil’.
+
+     Alias: ‘-same-items-p’.
+
+          (-same-items? '(1 2 3) '(1 2 3))
+              ⇒ t
+          (-same-items? '(1 1 2 3) '(3 3 2 1))
+              ⇒ t
+          (-same-items? '(1 2 3) '(1 2 3 4))
+              ⇒ nil
+
+\1f
+File: dash.info,  Node: Other list operations,  Next: Tree operations,  Prev: Set operations,  Up: Functions
+
+2.10 Other list operations
+==========================
+
+Other list functions not fit to be classified elsewhere.
+
+ -- Function: -rotate (n list)
+     Rotate LIST N places to the right (left if N is negative).  The
+     time complexity is O(n).
+
+          (-rotate 3 '(1 2 3 4 5 6 7))
+              ⇒ (5 6 7 1 2 3 4)
+          (-rotate -3 '(1 2 3 4 5 6 7))
+              ⇒ (4 5 6 7 1 2 3)
+          (-rotate 16 '(1 2 3 4 5 6 7))
+              ⇒ (6 7 1 2 3 4 5)
+
+ -- Function: -cons* (&rest args)
+     Make a new list from the elements of ARGS.  The last 2 elements of
+     ARGS are used as the final cons of the result, so if the final
+     element of ARGS is not a list, the result is a dotted list.  With
+     no ARGS, return ‘nil’.
+
+          (-cons* 1 2)
+              ⇒ (1 . 2)
+          (-cons* 1 2 3)
+              ⇒ (1 2 . 3)
+          (-cons* 1)
+              ⇒ 1
+
+ -- Function: -snoc (list elem &rest elements)
+     Append ELEM to the end of the list.
+
+     This is like ‘cons’, but operates on the end of list.
+
+     If any ELEMENTS are given, append them to the list as well.
+
+          (-snoc '(1 2 3) 4)
+              ⇒ (1 2 3 4)
+          (-snoc '(1 2 3) 4 5 6)
+              ⇒ (1 2 3 4 5 6)
+          (-snoc '(1 2 3) '(4 5 6))
+              ⇒ (1 2 3 (4 5 6))
+
+ -- Function: -interpose (sep list)
+     Return a new list of all elements in LIST separated by SEP.
+
+          (-interpose "-" ())
+              ⇒ ()
+          (-interpose "-" '("a"))
+              ⇒ ("a")
+          (-interpose "-" '("a" "b" "c"))
+              ⇒ ("a" "-" "b" "-" "c")
+
+ -- Function: -interleave (&rest lists)
+     Return a new list of the first item in each list, then the second
+     etc.
+
+          (-interleave '(1 2) '("a" "b"))
+              ⇒ (1 "a" 2 "b")
+          (-interleave '(1 2) '("a" "b") '("A" "B"))
+              ⇒ (1 "a" "A" 2 "b" "B")
+          (-interleave '(1 2 3) '("a" "b"))
+              ⇒ (1 "a" 2 "b")
+
+ -- Function: -iota (count &optional start step)
+     Return a list containing COUNT numbers.  Starts from START and adds
+     STEP each time.  The default START is zero, the default STEP is 1.
+     This function takes its name from the corresponding primitive in
+     the APL language.
+
+          (-iota 6)
+              ⇒ (0 1 2 3 4 5)
+          (-iota 4 2.5 -2)
+              ⇒ (2.5 0.5 -1.5 -3.5)
+          (-iota -1)
+              error→ Wrong type argument: natnump, -1
+
+ -- Function: -zip-with (fn list1 list2)
+     Zip LIST1 and LIST2 into a new list using the function FN.  That
+     is, apply FN pairwise taking as first argument the next element of
+     LIST1 and as second argument the next element of LIST2 at the
+     corresponding position.  The result is as long as the shorter list.
+
+     This function’s anaphoric counterpart is ‘--zip-with’.
+
+     For other zips, see also ‘-zip-lists’ (*note -zip-lists::) and
+     ‘-zip-fill’ (*note -zip-fill::).
+
+          (-zip-with #'+ '(1 2 3 4) '(5 6 7))
+              ⇒ (6 8 10)
+          (-zip-with #'cons '(1 2 3) '(4 5 6 7))
+              ⇒ ((1 . 4) (2 . 5) (3 . 6))
+          (--zip-with (format "%s & %s" it other) '(Batman Jekyll) '(Robin Hyde))
+              ⇒ ("Batman & Robin" "Jekyll & Hyde")
+
+ -- Function: -zip-pair (list1 list2)
+     Zip LIST1 and LIST2 together.
+
+     Make a pair with the head of each list, followed by a pair with the
+     second element of each list, and so on.  The number of pairs
+     returned is equal to the length of the shorter input list.
+
+     See also: ‘-zip-lists’ (*note -zip-lists::).
+
+          (-zip-pair '(1 2 3 4) '(5 6 7))
+              ⇒ ((1 . 5) (2 . 6) (3 . 7))
+          (-zip-pair '(1 2 3) '(4 5 6))
+              ⇒ ((1 . 4) (2 . 5) (3 . 6))
+          (-zip-pair '(1 2) '(3))
+              ⇒ ((1 . 3))
+
+ -- Function: -zip-lists (&rest lists)
+     Zip LISTS together.
+
+     Group the head of each list, followed by the second element of each
+     list, and so on.  The number of returned groupings is equal to the
+     length of the shortest input list, and the length of each grouping
+     is equal to the number of input LISTS.
+
+     The return value is always a list of proper lists, in contrast to
+     ‘-zip’ (*note -zip::) which returns a list of dotted pairs when
+     only two input LISTS are provided.
+
+     See also: ‘-zip-pair’ (*note -zip-pair::).
+
+          (-zip-lists '(1 2 3) '(4 5 6))
+              ⇒ ((1 4) (2 5) (3 6))
+          (-zip-lists '(1 2 3) '(4 5 6 7))
+              ⇒ ((1 4) (2 5) (3 6))
+          (-zip-lists '(1 2) '(3 4 5) '(6))
+              ⇒ ((1 3 6))
+
+ -- Function: -zip-lists-fill (fill-value &rest lists)
+     Zip LISTS together, padding shorter lists with FILL-VALUE.  This is
+     like ‘-zip-lists’ (*note -zip-lists::) (which see), except it
+     retains all elements at positions beyond the end of the shortest
+     list.  The number of returned groupings is equal to the length of
+     the longest input list, and the length of each grouping is equal to
+     the number of input LISTS.
+
+          (-zip-lists-fill 0 '(1 2) '(3 4 5) '(6))
+              ⇒ ((1 3 6) (2 4 0) (0 5 0))
+          (-zip-lists-fill 0 '(1 2) '(3 4) '(5 6))
+              ⇒ ((1 3 5) (2 4 6))
+          (-zip-lists-fill 0 '(1 2 3) nil)
+              ⇒ ((1 0) (2 0) (3 0))
+
+ -- Function: -zip (&rest lists)
+     Zip LISTS together.
+
+     Group the head of each list, followed by the second element of each
+     list, and so on.  The number of returned groupings is equal to the
+     length of the shortest input list, and the number of items in each
+     grouping is equal to the number of input LISTS.
+
+     If only two LISTS are provided as arguments, return the groupings
+     as a list of dotted pairs.  Otherwise, return the groupings as a
+     list of proper lists.
+
+     Since the return value changes form depending on the number of
+     arguments, it is generally recommended to use ‘-zip-lists’ (*note
+     -zip-lists::) instead, or ‘-zip-pair’ (*note -zip-pair::) if a list
+     of dotted pairs is desired.
+
+     See also: ‘-unzip’ (*note -unzip::).
+
+          (-zip '(1 2 3 4) '(5 6 7) '(8 9))
+              ⇒ ((1 5 8) (2 6 9))
+          (-zip '(1 2 3) '(4 5 6) '(7 8 9))
+              ⇒ ((1 4 7) (2 5 8) (3 6 9))
+          (-zip '(1 2 3))
+              ⇒ ((1) (2) (3))
+
+ -- Function: -zip-fill (fill-value &rest lists)
+     Zip LISTS together, padding shorter lists with FILL-VALUE.  This is
+     like ‘-zip’ (*note -zip::) (which see), except it retains all
+     elements at positions beyond the end of the shortest list.  The
+     number of returned groupings is equal to the length of the longest
+     input list, and the length of each grouping is equal to the number
+     of input LISTS.
+
+     Since the return value changes form depending on the number of
+     arguments, it is generally recommended to use ‘-zip-lists-fill’
+     (*note -zip-lists-fill::) instead, unless a list of dotted pairs is
+     explicitly desired.
+
+          (-zip-fill 0 '(1 2 3) '(4 5))
+              ⇒ ((1 . 4) (2 . 5) (3 . 0))
+          (-zip-fill 0 () '(1 2 3))
+              ⇒ ((0 . 1) (0 . 2) (0 . 3))
+          (-zip-fill 0 '(1 2) '(3 4) '(5 6))
+              ⇒ ((1 3 5) (2 4 6))
+
+ -- Function: -unzip-lists (lists)
+     Unzip LISTS.
+
+     This works just like ‘-zip-lists’ (*note -zip-lists::) (which see),
+     but takes a list of lists instead of a variable number of
+     arguments, such that
+
+     (-unzip-lists (-zip-lists ARGS...))
+
+     is identity (given that the lists comprising ARGS are of the same
+     length).
+
+          (-unzip-lists (-zip-lists '(1 2) '(3 4) '(5 6)))
+              ⇒ ((1 2) (3 4) (5 6))
+          (-unzip-lists '((1 2 3) (4 5) (6 7) (8 9)))
+              ⇒ ((1 4 6 8) (2 5 7 9))
+          (-unzip-lists '((1 2 3) (4 5 6)))
+              ⇒ ((1 4) (2 5) (3 6))
+
+ -- Function: -unzip (lists)
+     Unzip LISTS.
+
+     This works just like ‘-zip’ (*note -zip::) (which see), but takes a
+     list of lists instead of a variable number of arguments, such that
+
+     (-unzip (-zip L1 L2 L3 ...))
+
+     is identity (given that the lists are of the same length, and that
+     ‘-zip’ (*note -zip::) is not called with two arguments, because of
+     the caveat described in its docstring).
+
+     Note in particular that calling ‘-unzip’ (*note -unzip::) on a list
+     of two lists will return a list of dotted pairs.
+
+     Since the return value changes form depending on the number of
+     LISTS, it is generally recommended to use ‘-unzip-lists’ (*note
+     -unzip-lists::) instead.
+
+          (-unzip (-zip '(1 2) '(3 4) '(5 6)))
+              ⇒ ((1 . 2) (3 . 4) (5 . 6))
+          (-unzip '((1 2 3) (4 5 6)))
+              ⇒ ((1 . 4) (2 . 5) (3 . 6))
+          (-unzip '((1 2 3) (4 5) (6 7) (8 9)))
+              ⇒ ((1 4 6 8) (2 5 7 9))
+
+ -- Function: -pad (fill-value &rest lists)
+     Pad each of LISTS with FILL-VALUE until they all have equal
+     lengths.
+
+     Ensure all LISTS are as long as the longest one by repeatedly
+     appending FILL-VALUE to the shorter lists, and return the resulting
+     LISTS.
+
+          (-pad 0 ())
+              ⇒ (nil)
+          (-pad 0 '(1 2) '(3 4))
+              ⇒ ((1 2) (3 4))
+          (-pad 0 '(1 2) '(3 4 5 6) '(7 8 9))
+              ⇒ ((1 2 0 0) (3 4 5 6) (7 8 9 0))
+
+ -- Function: -table (fn &rest lists)
+     Compute outer product of LISTS using function FN.
+
+     The function FN should have the same arity as the number of
+     supplied lists.
+
+     The outer product is computed by applying fn to all possible
+     combinations created by taking one element from each list in order.
+     The dimension of the result is (length lists).
+
+     See also: ‘-table-flat’ (*note -table-flat::)
+
+          (-table '* '(1 2 3) '(1 2 3))
+              ⇒ ((1 2 3) (2 4 6) (3 6 9))
+          (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4)))
+              ⇒ ((7 15) (10 22))
+          (apply '-table 'list (-repeat 3 '(1 2)))
+              ⇒ ((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2))))
+
+ -- Function: -table-flat (fn &rest lists)
+     Compute flat outer product of LISTS using function FN.
+
+     The function FN should have the same arity as the number of
+     supplied lists.
+
+     The outer product is computed by applying fn to all possible
+     combinations created by taking one element from each list in order.
+     The results are flattened, ignoring the tensor structure of the
+     result.  This is equivalent to calling:
+
+     (-flatten-n (1- (length lists)) (apply ’-table fn lists))
+
+     but the implementation here is much more efficient.
+
+     See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note
+     -table::)
+
+          (-table-flat 'list '(1 2 3) '(a b c))
+              ⇒ ((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c))
+          (-table-flat '* '(1 2 3) '(1 2 3))
+              ⇒ (1 2 3 2 4 6 3 6 9)
+          (apply '-table-flat 'list (-repeat 3 '(1 2)))
+              ⇒ ((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2))
+
+ -- Function: -first (pred list)
+     Return the first item in LIST for which PRED returns non-‘nil’.
+     Return ‘nil’ if no such element is found.
+
+     To get the first item in the list no questions asked, use
+     ‘-first-item’ (*note -first-item::).
+
+     Alias: ‘-find’.
+
+     This function’s anaphoric counterpart is ‘--first’.
+
+          (-first #'natnump '(-1 0 1))
+              ⇒ 0
+          (-first #'null '(1 2 3))
+              ⇒ nil
+          (--first (> it 2) '(1 2 3))
+              ⇒ 3
+
+ -- Function: -last (pred list)
+     Return the last x in LIST where (PRED x) is non-‘nil’, else ‘nil’.
+
+          (-last 'even? '(1 2 3 4 5 6 3 3 3))
+              ⇒ 6
+          (-last 'even? '(1 3 7 5 9))
+              ⇒ nil
+          (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one"))
+              ⇒ "short"
+
+ -- Function: -first-item (list)
+     Return the first item of LIST, or ‘nil’ on an empty list.
+
+     See also: ‘-second-item’ (*note -second-item::), ‘-last-item’
+     (*note -last-item::), etc.
+
+          (-first-item ())
+              ⇒ ()
+          (-first-item '(1 2 3 4 5))
+              ⇒ 1
+          (let ((list (list 1 2 3))) (setf (-first-item list) 5) list)
+              ⇒ (5 2 3)
+
+ -- Function: -second-item (list)
+     Return the second item of LIST, or ‘nil’ if LIST is too short.
+
+     See also: ‘-first-item’ (*note -first-item::), ‘-third-item’ (*note
+     -third-item::), etc.
+
+          (-second-item ())
+              ⇒ ()
+          (-second-item '(1 2 3 4 5))
+              ⇒ 2
+          (let ((list (list 1 2))) (setf (-second-item list) 5) list)
+              ⇒ (1 5)
+
+ -- Function: -third-item (list)
+     Return the third item of LIST, or ‘nil’ if LIST is too short.
+
+     See also: ‘-second-item’ (*note -second-item::), ‘-fourth-item’
+     (*note -fourth-item::), etc.
+
+          (-third-item ())
+              ⇒ ()
+          (-third-item '(1 2))
+              ⇒ ()
+          (-third-item '(1 2 3 4 5))
+              ⇒ 3
+
+ -- Function: -fourth-item (list)
+     Return the fourth item of LIST, or ‘nil’ if LIST is too short.
+
+     See also: ‘-third-item’ (*note -third-item::), ‘-fifth-item’ (*note
+     -fifth-item::), etc.
+
+          (-fourth-item ())
+              ⇒ ()
+          (-fourth-item '(1 2 3))
+              ⇒ ()
+          (-fourth-item '(1 2 3 4 5))
+              ⇒ 4
+
+ -- Function: -fifth-item (list)
+     Return the fifth item of LIST, or ‘nil’ if LIST is too short.
+
+     See also: ‘-fourth-item’ (*note -fourth-item::), ‘-last-item’
+     (*note -last-item::), etc.
+
+          (-fifth-item ())
+              ⇒ ()
+          (-fifth-item '(1 2 3 4))
+              ⇒ ()
+          (-fifth-item '(1 2 3 4 5))
+              ⇒ 5
+
+ -- Function: -last-item (list)
+     Return the last item of LIST, or ‘nil’ on an empty list.
+
+     See also: ‘-first-item’ (*note -first-item::), etc.
+
+          (-last-item ())
+              ⇒ ()
+          (-last-item '(1 2 3 4 5))
+              ⇒ 5
+          (let ((list (list 1 2 3))) (setf (-last-item list) 5) list)
+              ⇒ (1 2 5)
+
+ -- Function: -butlast (list)
+     Return a list of all items in list except for the last.
+
+          (-butlast '(1 2 3))
+              ⇒ (1 2)
+          (-butlast '(1 2))
+              ⇒ (1)
+          (-butlast '(1))
+              ⇒ nil
+
+ -- Function: -sort (comparator list)
+     Sort LIST, stably, comparing elements using COMPARATOR.  Return the
+     sorted list.  LIST is NOT modified by side effects.  COMPARATOR is
+     called with two elements of LIST, and should return non-‘nil’ if
+     the first element should sort before the second.
+
+          (-sort #'< '(3 1 2))
+              ⇒ (1 2 3)
+          (-sort #'> '(3 1 2))
+              ⇒ (3 2 1)
+          (--sort (< it other) '(3 1 2))
+              ⇒ (1 2 3)
+
+ -- Function: -list (arg)
+     Ensure ARG is a list.  If ARG is already a list, return it as is
+     (not a copy).  Otherwise, return a new list with ARG as its only
+     element.
+
+     Another supported calling convention is (-list &rest ARGS).  In
+     this case, if ARG is not a list, a new list with all of ARGS as
+     elements is returned.  This use is supported for backward
+     compatibility and is otherwise deprecated.
+
+          (-list 1)
+              ⇒ (1)
+          (-list ())
+              ⇒ ()
+          (-list '(1 2 3))
+              ⇒ (1 2 3)
+
+ -- Function: -fix (fn list)
+     Compute the (least) fixpoint of FN with initial input LIST.
+
+     FN is called at least once, results are compared with ‘equal’.
+
+          (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3)))
+              ⇒ ((1) (2) (3))
+          (let ((l '((starwars scifi) (jedi starwars warrior)))) (--fix (-uniq (--mapcat (cons it (cdr (assq it l))) it)) '(jedi book)))
+              ⇒ (jedi starwars warrior scifi book)
+
+\1f
+File: dash.info,  Node: Tree operations,  Next: Threading macros,  Prev: Other list operations,  Up: Functions
+
+2.11 Tree operations
+====================
+
+Functions pretending lists are trees.
+
+ -- Function: -tree-seq (branch children tree)
+     Return a sequence of the nodes in TREE, in depth-first search
+     order.
+
+     BRANCH is a predicate of one argument that returns non-‘nil’ if the
+     passed argument is a branch, that is, a node that can have
+     children.
+
+     CHILDREN is a function of one argument that returns the children of
+     the passed branch node.
+
+     Non-branch nodes are simply copied.
+
+          (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7))))
+              ⇒ ((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7)
+          (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7))))
+              ⇒ ((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1)
+          (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]])
+              ⇒ ([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7)
+
+ -- Function: -tree-map (fn tree)
+     Apply FN to each element of TREE while preserving the tree
+     structure.
+
+          (-tree-map '1+ '(1 (2 3) (4 (5 6) 7)))
+              ⇒ (2 (3 4) (5 (6 7) 8))
+          (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4))
+              ⇒ ((1 . 2) ((2 . 4) (3 . 8)) (4 . 16))
+          (--tree-map (length it) '("<body>" ("<p>" "text" "</p>") "</body>"))
+              ⇒ (6 (3 4 4) 7)
+
+ -- Function: -tree-map-nodes (pred fun tree)
+     Call FUN on each node of TREE that satisfies PRED.
+
+     If PRED returns ‘nil’, continue descending down this node.  If PRED
+     returns non-‘nil’, apply FUN to this node and do not descend
+     further.
+
+          (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8)))
+              ⇒ (1 5 4 (5 13 8))
+          (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8)))
+              ⇒ (1 ":foo" 4 ((5 6 ":bar") ":baz" 8))
+          (--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d))))
+              ⇒ (with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode)))
+
+ -- Function: -tree-reduce (fn tree)
+     Use FN to reduce elements of list TREE.  If elements of TREE are
+     lists themselves, apply the reduction recursively.
+
+     FN is first applied to first element of the list and second
+     element, then on this result and third element from the list etc.
+
+     See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of
+     zero or one element handled.
+
+          (-tree-reduce '+ '(1 (2 3) (4 5)))
+              ⇒ 15
+          (-tree-reduce 'concat '("strings" (" on" " various") ((" levels"))))
+              ⇒ "strings on various levels"
+          (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "</" sn ">")))) '(body (p "some words") (div "more" (b "bold") "words")))
+              ⇒ "<body><p>some words</p> <div>more <b>bold</b> words</div></body>"
+
+ -- Function: -tree-reduce-from (fn init-value tree)
+     Use FN to reduce elements of list TREE.  If elements of TREE are
+     lists themselves, apply the reduction recursively.
+
+     FN is first applied to INIT-VALUE and first element of the list,
+     then on this result and second element from the list etc.
+
+     The initial value is ignored on cons pairs as they always contain
+     two elements.
+
+          (-tree-reduce-from '+ 1 '(1 (1 1) ((1))))
+              ⇒ 8
+          (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7)))
+              ⇒ ((7 6) ((5 4) 3 2) 1)
+
+ -- Function: -tree-mapreduce (fn folder tree)
+     Apply FN to each element of TREE, and make a list of the results.
+     If elements of TREE are lists themselves, apply FN recursively to
+     elements of these nested lists.
+
+     Then reduce the resulting lists using FOLDER and initial value
+     INIT-VALUE.  See ‘-reduce-r-from’ (*note -reduce-r-from::).
+
+     This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::)
+     after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it
+     only traverse the structure once.
+
+          (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9))))
+              ⇒ (1 2 3 4 5 6 7 8 9)
+          (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3))))
+              ⇒ 9
+          (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3))))
+              ⇒ 3
+
+ -- Function: -tree-mapreduce-from (fn folder init-value tree)
+     Apply FN to each element of TREE, and make a list of the results.
+     If elements of TREE are lists themselves, apply FN recursively to
+     elements of these nested lists.
+
+     Then reduce the resulting lists using FOLDER and initial value
+     INIT-VALUE.  See ‘-reduce-r-from’ (*note -reduce-r-from::).
+
+     This is the same as calling ‘-tree-reduce-from’ (*note
+     -tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is
+     twice as fast as it only traverse the structure once.
+
+          (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9))))
+              ⇒ 362880
+          (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3))))
+              ⇒ (2 (4 (8 18) (4 2)) (14 (8 6)))
+          (concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elisp-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam)))))
+              ⇒ "{elisp-mode : {foo : {bar -> booze}, baz -> qux}, c-mode : {foo -> bla, bum -> bam}}"
+
+ -- Function: -clone (list)
+     Create a deep copy of LIST.  The new list has the same elements and
+     structure but all cons are replaced with new ones.  This is useful
+     when you need to clone a structure such as plist or alist.
+
+          (let* ((a (list (list 1))) (b (-clone a))) (setcar (car a) 2) b)
+              ⇒ ((1))
+
+\1f
+File: dash.info,  Node: Threading macros,  Next: Binding,  Prev: Tree operations,  Up: Functions
+
+2.12 Threading macros
+=====================
+
+Macros that conditionally combine sequential forms for brevity or
+readability.
+
+ -- Macro: -> (x &optional form &rest more)
+     Thread the expr through the forms.  Insert X as the second item in
+     the first form, making a list of it if it is not a list already.
+     If there are more forms, insert the first form as the second item
+     in second form, etc.
+
+          (-> '(2 3 5))
+              ⇒ (2 3 5)
+          (-> '(2 3 5) (append '(8 13)))
+              ⇒ (2 3 5 8 13)
+          (-> '(2 3 5) (append '(8 13)) (-slice 1 -1))
+              ⇒ (3 5 8)
+
+ -- Macro: ->> (x &optional form &rest more)
+     Thread the expr through the forms.  Insert X as the last item in
+     the first form, making a list of it if it is not a list already.
+     If there are more forms, insert the first form as the last item in
+     second form, etc.
+
+          (->> '(1 2 3) (-map 'square))
+              ⇒ (1 4 9)
+          (->> '(1 2 3) (-map 'square) (-remove 'even?))
+              ⇒ (1 9)
+          (->> '(1 2 3) (-map 'square) (-reduce '+))
+              ⇒ 14
+
+ -- Macro: --> (x &rest forms)
+     Starting with the value of X, thread each expression through FORMS.
+
+     Insert X at the position signified by the symbol ‘it’ in the first
+     form.  If there are more forms, insert the first form at the
+     position signified by ‘it’ in the second form, etc.
+
+          (--> "def" (concat "abc" it "ghi"))
+              ⇒ "abcdefghi"
+          (--> "def" (concat "abc" it "ghi") (upcase it))
+              ⇒ "ABCDEFGHI"
+          (--> "def" (concat "abc" it "ghi") upcase)
+              ⇒ "ABCDEFGHI"
+
+ -- Macro: -as-> (value variable &rest forms)
+     Starting with VALUE, thread VARIABLE through FORMS.
+
+     In the first form, bind VARIABLE to VALUE.  In the second form,
+     bind VARIABLE to the result of the first form, and so forth.
+
+          (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var))
+              ⇒ (8)
+          (-as-> 3 my-var 1+)
+              ⇒ 4
+          (-as-> 3 my-var)
+              ⇒ 3
+
+ -- Macro: -some-> (x &optional form &rest more)
+     When expr is non-‘nil’, thread it through the first form (via ‘->’
+     (*note ->::)), and when that result is non-‘nil’, through the next
+     form, etc.
+
+          (-some-> '(2 3 5))
+              ⇒ (2 3 5)
+          (-some-> 5 square)
+              ⇒ 25
+          (-some-> 5 even? square)
+              ⇒ nil
+
+ -- Macro: -some->> (x &optional form &rest more)
+     When expr is non-‘nil’, thread it through the first form (via ‘->>’
+     (*note ->>::)), and when that result is non-‘nil’, through the next
+     form, etc.
+
+          (-some->> '(1 2 3) (-map 'square))
+              ⇒ (1 4 9)
+          (-some->> '(1 3 5) (-last 'even?) (+ 100))
+              ⇒ nil
+          (-some->> '(2 4 6) (-last 'even?) (+ 100))
+              ⇒ 106
+
+ -- Macro: -some--> (expr &rest forms)
+     Thread EXPR through FORMS via ‘-->’ (*note -->::), while the result
+     is non-‘nil’.  When EXPR evaluates to non-‘nil’, thread the result
+     through the first of FORMS, and when that result is non-‘nil’,
+     thread it through the next form, etc.
+
+          (-some--> "def" (concat "abc" it "ghi"))
+              ⇒ "abcdefghi"
+          (-some--> nil (concat "abc" it "ghi"))
+              ⇒ nil
+          (-some--> '(0 1) (-remove #'natnump it) (append it it) (-map #'1+ it))
+              ⇒ ()
+
+ -- Macro: -doto (init &rest forms)
+     Evaluate INIT and pass it as argument to FORMS with ‘->’ (*note
+     ->::).  The RESULT of evaluating INIT is threaded through each of
+     FORMS individually using ‘->’ (*note ->::), which see.  The return
+     value is RESULT, which FORMS may have modified by side effect.
+
+          (-doto (list 1 2 3) pop pop)
+              ⇒ (3)
+          (-doto (cons 1 2) (setcar 3) (setcdr 4))
+              ⇒ (3 . 4)
+          (gethash 'k (--doto (make-hash-table) (puthash 'k 'v it)))
+              ⇒ v
+
+\1f
+File: dash.info,  Node: Binding,  Next: Side effects,  Prev: Threading macros,  Up: Functions
+
+2.13 Binding
+============
+
+Macros that combine ‘let’ and ‘let*’ with destructuring and flow
+control.
+
+ -- Macro: -when-let ((var val) &rest body)
+     If VAL evaluates to non-‘nil’, bind it to VAR and execute body.
+
+     Note: binding is done according to ‘-let’ (*note -let::).
+
+          (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2))
+              ⇒ 5
+          (-when-let ((&plist :foo foo) (list :foo "foo")) foo)
+              ⇒ "foo"
+          (-when-let ((&plist :foo foo) (list :bar "bar")) foo)
+              ⇒ nil
+
+ -- Macro: -when-let* (vars-vals &rest body)
+     If all VALS evaluate to true, bind them to their corresponding VARS
+     and execute body.  VARS-VALS should be a list of (VAR VAL) pairs.
+
+     Note: binding is done according to ‘-let*’ (*note -let*::).  VALS
+     are evaluated sequentially, and evaluation stops after the first
+     ‘nil’ VAL is encountered.
+
+          (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z))
+              ⇒ 15
+          (-when-let* ((x 5) (y nil) (z 7)) (+ x y z))
+              ⇒ nil
+
+ -- Macro: -if-let ((var val) then &rest else)
+     If VAL evaluates to non-‘nil’, bind it to VAR and do THEN,
+     otherwise do ELSE.
+
+     Note: binding is done according to ‘-let’ (*note -let::).
+
+          (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7)
+              ⇒ 7
+          (--if-let (even? 4) it nil)
+              ⇒ t
+
+ -- Macro: -if-let* (vars-vals then &rest else)
+     If all VALS evaluate to true, bind them to their corresponding VARS
+     and do THEN, otherwise do ELSE.  VARS-VALS should be a list of (VAR
+     VAL) pairs.
+
+     Note: binding is done according to ‘-let*’ (*note -let*::).  VALS
+     are evaluated sequentially, and evaluation stops after the first
+     ‘nil’ VAL is encountered.
+
+          (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo")
+              ⇒ 15
+          (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo")
+              ⇒ "foo"
+          (-if-let* (((_ _ x) '(nil nil 7))) x)
+              ⇒ 7
+
+ -- Macro: -let (varlist &rest body)
+     Bind variables according to VARLIST then eval BODY.
+
+     VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
+     PATTERN is matched against the SOURCE "structurally".  SOURCE is
+     only evaluated once for each PATTERN.  Each PATTERN is matched
+     recursively, and can therefore contain sub-patterns which are
+     matched against corresponding sub-expressions of SOURCE.
+
+     All the SOURCEs are evalled before any symbols are bound (i.e.  "in
+     parallel").
+
+     If VARLIST only contains one (PATTERN SOURCE) element, you can
+     optionally specify it using a vector and discarding the outer-most
+     parens.  Thus
+
+     (-let ((PATTERN SOURCE)) ...)
+
+     becomes
+
+     (-let [PATTERN SOURCE] ...).
+
+     ‘-let’ (*note -let::) uses a convention of not binding places
+     (symbols) starting with _ whenever it’s possible.  You can use this
+     to skip over entries you don’t care about.  However, this is not
+     *always* possible (as a result of implementation) and these symbols
+     might get bound to undefined values.
+
+     Following is the overview of supported patterns.  Remember that
+     patterns can be matched recursively, so every a, b, aK in the
+     following can be a matching construct and not necessarily a
+     symbol/variable.
+
+     Symbol:
+
+     a - bind the SOURCE to A.  This is just like regular ‘let’.
+
+     Conses and lists:
+
+     (a) - bind ‘car’ of cons/list to A
+
+     (a .  b) - bind car of cons to A and ‘cdr’ to B
+
+     (a b) - bind car of list to A and ‘cadr’ to B
+
+     (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to
+     A3...
+
+     (a1 a2 a3 ... aN .  rest) - as above, but bind the Nth cdr to REST.
+
+     Vectors:
+
+     [a] - bind 0th element of a non-list sequence to A (works with
+     vectors, strings, bit arrays...)
+
+     [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st
+     to A1, 2nd to A2, ...  If the PATTERN is shorter than SOURCE, the
+     values at places not in PATTERN are ignored.  If the PATTERN is
+     longer than SOURCE, an ‘error’ is thrown.
+
+     [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the
+     sequence to REST.  This is conceptually the same as improper list
+     matching (a1 a2 ... aN .  rest)
+
+     Key/value stores:
+
+     (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+     SOURCE plist to aK. If the value is not found, aK is ‘nil’.  Uses
+     ‘plist-get’ to fetch values.
+
+     (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the
+     SOURCE alist to aK. If the value is not found, aK is ‘nil’.  Uses
+     ‘assoc’ to fetch values.
+
+     (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the
+     SOURCE hash table to aK. If the value is not found, aK is ‘nil’.
+     Uses ‘gethash’ to fetch values.
+
+     Further, special keyword &keys supports "inline" matching of
+     plist-like key-value pairs, similarly to &keys keyword of
+     ‘cl-defun’.
+
+     (a1 a2 ... aN &keys key1 b1 ... keyN bK)
+
+     This binds N values from the list to a1 ... aN, then interprets the
+     cdr as a plist (see key/value matching above).
+
+     A shorthand notation for kv-destructuring exists which allows the
+     patterns be optionally left out and derived from the key name in
+     the following fashion:
+
+     - a key :foo is converted into ‘foo’ pattern, - a key ’bar is
+     converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’
+     pattern.
+
+     That is, the entire value under the key is bound to the derived
+     variable without any further destructuring.
+
+     This is possible only when the form following the key is not a
+     valid pattern (i.e.  not a symbol, a cons cell or a vector).
+     Otherwise the matching proceeds as usual and in case of an invalid
+     spec fails with an error.
+
+     Thus the patterns are normalized as follows:
+
+     ;; derive all the missing patterns (&plist :foo ’bar "baz") =>
+     (&plist :foo foo ’bar bar "baz" baz)
+
+     ;; we can specify some but not others (&plist :foo ’bar
+     explicit-bar) => (&plist :foo foo ’bar explicit-bar)
+
+     ;; nothing happens, we store :foo in x (&plist :foo x) => (&plist
+     :foo x)
+
+     ;; nothing happens, we match recursively (&plist :foo (a b c)) =>
+     (&plist :foo (a b c))
+
+     You can name the source using the syntax SYMBOL &as PATTERN.  This
+     syntax works with lists (proper or improper), vectors and all types
+     of maps.
+
+     (list &as a b c) (list 1 2 3)
+
+     binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
+
+     Similarly:
+
+     (bounds &as beg .  end) (cons 1 2)
+
+     binds BEG to 1, END to 2 and BOUNDS to (1 .  2).
+
+     (items &as first .  rest) (list 1 2 3)
+
+     binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
+
+     [vect &as _ b c] [1 2 3]
+
+     binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as
+     usual).
+
+     (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+     binds B to 2 and PLIST to (:a 1 :b 2 :c 3).  Same for &alist and
+     &hash.
+
+     This is especially useful when we want to capture the result of a
+     computation and destructure at the same time.  Consider the form
+     (function-returning-complex-structure) returning a list of two
+     vectors with two items each.  We want to capture this entire result
+     and pass it to another computation, but at the same time we want to
+     get the second item from each vector.  We can achieve it with
+     pattern
+
+     (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+     Note: Clojure programmers may know this feature as the ":as
+     binding".  The difference is that we put the &as at the front
+     because we need to support improper list binding.
+
+          (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d))
+              ⇒ (1 2 3 4)
+          (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d))
+              ⇒ (1 2 3 (4 5 6))
+          (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar))
+              ⇒ (1 2)
+
+ -- Macro: -let* (varlist &rest body)
+     Bind variables according to VARLIST then eval BODY.
+
+     VARLIST is a list of lists of the form (PATTERN SOURCE).  Each
+     PATTERN is matched against the SOURCE structurally.  SOURCE is only
+     evaluated once for each PATTERN.
+
+     Each SOURCE can refer to the symbols already bound by this VARLIST.
+     This is useful if you want to destructure SOURCE recursively but
+     also want to name the intermediate structures.
+
+     See ‘-let’ (*note -let::) for the list of all possible patterns.
+
+          (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d))
+              ⇒ (1 2 3 4)
+          (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d))
+              ⇒ (1 (2 . 3) 2 3)
+          (-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar))
+              ⇒ (1 a b c (a b c))
+
+ -- Macro: -lambda (match-form &rest body)
+     Return a lambda which destructures its input as MATCH-FORM and
+     executes BODY.
+
+     Note that you have to enclose the MATCH-FORM in a pair of parens,
+     such that:
+
+     (-lambda (x) body) (-lambda (x y ...) body)
+
+     has the usual semantics of ‘lambda’.  Furthermore, these get
+     translated into normal ‘lambda’, so there is no performance
+     penalty.
+
+     See ‘-let’ (*note -let::) for a description of the destructuring
+     mechanism.
+
+          (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6)))
+              ⇒ (3 7 11)
+          (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6]))
+              ⇒ (3 7 11)
+          (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6))
+              ⇒ (2 3 5 6)
+
+ -- Macro: -setq ([match-form val] ...)
+     Bind each MATCH-FORM to the value of its VAL.
+
+     MATCH-FORM destructuring is done according to the rules of ‘-let’
+     (*note -let::).
+
+     This macro allows you to bind multiple variables by destructuring
+     the value, so for example:
+
+     (-setq (a b) x (&plist :c c) plist)
+
+     expands roughly speaking to the following code
+
+     (setq a (car x) b (cadr x) c (plist-get plist :c))
+
+     Care is taken to only evaluate each VAL once so that in case of
+     multiple assignments it does not cause unexpected side effects.
+
+          (let (a) (-setq a 1) a)
+              ⇒ 1
+          (let (a b) (-setq (a b) (list 1 2)) (list a b))
+              ⇒ (1 2)
+          (let (c) (-setq (&plist :c c) (list :c "c")) c)
+              ⇒ "c"
+
+\1f
+File: dash.info,  Node: Side effects,  Next: Destructive operations,  Prev: Binding,  Up: Functions
+
+2.14 Side effects
+=================
+
+Functions iterating over lists for side effect only.
+
+ -- Function: -each (list fn)
+     Call FN on each element of LIST.  Return ‘nil’; this function is
+     intended for side effects.
+
+     Its anaphoric counterpart is ‘--each’.
+
+     For access to the current element’s index in LIST, see
+     ‘-each-indexed’ (*note -each-indexed::).
+
+          (let (l) (-each '(1 2 3) (lambda (x) (push x l))) l)
+              ⇒ (3 2 1)
+          (let (l) (--each '(1 2 3) (push it l)) l)
+              ⇒ (3 2 1)
+          (-each '(1 2 3) #'identity)
+              ⇒ nil
+
+ -- Function: -each-while (list pred fn)
+     Call FN on each ITEM in LIST, while (PRED ITEM) is non-‘nil’.  Once
+     an ITEM is reached for which PRED returns ‘nil’, FN is no longer
+     called.  Return ‘nil’; this function is intended for side effects.
+
+     Its anaphoric counterpart is ‘--each-while’.
+
+          (let (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l)
+              ⇒ (4 2)
+          (let (l) (--each-while '(1 2 3 4) (< it 3) (push it l)) l)
+              ⇒ (2 1)
+          (let ((s 0)) (--each-while '(1 3 4 5) (< it 5) (setq s (+ s it))) s)
+              ⇒ 8
+
+ -- Function: -each-indexed (list fn)
+     Call FN on each index and element of LIST.  For each ITEM at INDEX
+     in LIST, call (funcall FN INDEX ITEM).  Return ‘nil’; this function
+     is intended for side effects.
+
+     See also: ‘-map-indexed’ (*note -map-indexed::).
+
+          (let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l)
+              ⇒ ((c 2) (b 1) (a 0))
+          (let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l)
+              ⇒ ((c 2) (b 1) (a 0))
+          (let (l) (--each-indexed () (push it l)) l)
+              ⇒ ()
+
+ -- Function: -each-r (list fn)
+     Call FN on each element of LIST in reversed order.  Return ‘nil’;
+     this function is intended for side effects.
+
+     Its anaphoric counterpart is ‘--each-r’.
+
+          (let (l) (-each-r '(1 2 3) (lambda (x) (push x l))) l)
+              ⇒ (1 2 3)
+          (let (l) (--each-r '(1 2 3) (push it l)) l)
+              ⇒ (1 2 3)
+          (-each-r '(1 2 3) #'identity)
+              ⇒ nil
+
+ -- Function: -each-r-while (list pred fn)
+     Call FN on each ITEM in reversed LIST, while (PRED ITEM) is
+     non-‘nil’.  Once an ITEM is reached for which PRED returns ‘nil’,
+     FN is no longer called.  Return ‘nil’; this function is intended
+     for side effects.
+
+     Its anaphoric counterpart is ‘--each-r-while’.
+
+          (let (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l)
+              ⇒ (6)
+          (let (l) (--each-r-while '(1 2 3 4) (>= it 3) (push it l)) l)
+              ⇒ (3 4)
+          (let ((s 0)) (--each-r-while '(1 2 3 5) (> it 1) (setq s (+ s it))) s)
+              ⇒ 10
+
+ -- Function: -dotimes (num fn)
+     Call FN NUM times, presumably for side effects.  FN is called with
+     a single argument on successive integers running from 0, inclusive,
+     to NUM, exclusive.  FN is not called if NUM is less than 1.
+
+     This function’s anaphoric counterpart is ‘--dotimes’.
+
+          (let (s) (-dotimes 3 (lambda (n) (push n s))) s)
+              ⇒ (2 1 0)
+          (let (s) (-dotimes 0 (lambda (n) (push n s))) s)
+              ⇒ ()
+          (let (s) (--dotimes 5 (push it s)) s)
+              ⇒ (4 3 2 1 0)
+
+\1f
+File: dash.info,  Node: Destructive operations,  Next: Function combinators,  Prev: Side effects,  Up: Functions
+
+2.15 Destructive operations
+===========================
+
+Macros that modify variables holding lists.
+
+ -- Macro: !cons (car cdr)
+     Destructive: Set CDR to the cons of CAR and CDR.
+
+          (let (l) (!cons 5 l) l)
+              ⇒ (5)
+          (let ((l '(3))) (!cons 5 l) l)
+              ⇒ (5 3)
+
+ -- Macro: !cdr (list)
+     Destructive: Set LIST to the cdr of LIST.
+
+          (let ((l '(3))) (!cdr l) l)
+              ⇒ ()
+          (let ((l '(3 5))) (!cdr l) l)
+              ⇒ (5)
+
+\1f
+File: dash.info,  Node: Function combinators,  Prev: Destructive operations,  Up: Functions
+
+2.16 Function combinators
+=========================
+
+Functions that manipulate and compose other functions.
+
+ -- Function: -partial (fun &rest args)
+     Return a function that is a partial application of FUN to ARGS.
+     ARGS is a list of the first N arguments to pass to FUN.  The result
+     is a new function which does the same as FUN, except that the first
+     N arguments are fixed at the values with which this function was
+     called.
+
+          (funcall (-partial #'+ 5))
+              ⇒ 5
+          (funcall (-partial #'- 5) 3)
+              ⇒ 2
+          (funcall (-partial #'+ 5 2) 3)
+              ⇒ 10
+
+ -- Function: -rpartial (fn &rest args)
+     Return a function that is a partial application of FN to ARGS.
+     ARGS is a list of the last N arguments to pass to FN.  The result
+     is a new function which does the same as FN, except that the last N
+     arguments are fixed at the values with which this function was
+     called.  This is like ‘-partial’ (*note -partial::), except the
+     arguments are fixed starting from the right rather than the left.
+
+          (funcall (-rpartial #'- 5))
+              ⇒ -5
+          (funcall (-rpartial #'- 5) 8)
+              ⇒ 3
+          (funcall (-rpartial #'- 5 2) 10)
+              ⇒ 3
+
+ -- Function: -juxt (&rest fns)
+     Return a function that is the juxtaposition of FNS.  The returned
+     function takes a variable number of ARGS, applies each of FNS in
+     turn to ARGS, and returns the list of results.
+
+          (funcall (-juxt) 1 2)
+              ⇒ ()
+          (funcall (-juxt #'+ #'- #'* #'/) 7 5)
+              ⇒ (12 2 35 1)
+          (mapcar (-juxt #'number-to-string #'1+) '(1 2))
+              ⇒ (("1" 2) ("2" 3))
+
+ -- Function: -compose (&rest fns)
+     Compose FNS into a single composite function.  Return a function
+     that takes a variable number of ARGS, applies the last function in
+     FNS to ARGS, and returns the result of calling each remaining
+     function on the result of the previous function, right-to-left.  If
+     no FNS are given, return a variadic ‘identity’ function.
+
+          (funcall (-compose #'- #'1+ #'+) 1 2 3)
+              ⇒ -7
+          (funcall (-compose #'identity #'1+) 3)
+              ⇒ 4
+          (mapcar (-compose #'not #'stringp) '(nil ""))
+              ⇒ (t nil)
+
+ -- Function: -applify (fn)
+     Return a function that applies FN to a single list of args.  This
+     changes the arity of FN from taking N distinct arguments to taking
+     1 argument which is a list of N arguments.
+
+          (funcall (-applify #'+) nil)
+              ⇒ 0
+          (mapcar (-applify #'+) '((1 1 1) (1 2 3) (5 5 5)))
+              ⇒ (3 6 15)
+          (funcall (-applify #'<) '(3 6))
+              ⇒ t
+
+ -- Function: -on (op trans)
+     Return a function that calls TRANS on each arg and OP on the
+     results.  The returned function takes a variable number of
+     arguments, calls the function TRANS on each one in turn, and then
+     passes those results as the list of arguments to OP, in the same
+     order.
+
+     For example, the following pairs of expressions are morally
+     equivalent:
+
+     (funcall (-on #’+ #’1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3)) (funcall
+     (-on #’+ #’1+)) = (+)
+
+          (-sort (-on #'< #'length) '((1 2 3) (1) (1 2)))
+              ⇒ ((1) (1 2) (1 2 3))
+          (funcall (-on #'min #'string-to-number) "22" "2" "1" "12")
+              ⇒ 1
+          (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2)))
+              ⇒ (4)
+
+ -- Function: -flip (fn)
+     Return a function that calls FN with its arguments reversed.  The
+     returned function takes the same number of arguments as FN.
+
+     For example, the following two expressions are morally equivalent:
+
+     (funcall (-flip #’-) 1 2) = (- 2 1)
+
+     See also: ‘-rotate-args’ (*note -rotate-args::).
+
+          (-sort (-flip #'<) '(4 3 6 1))
+              ⇒ (6 4 3 1)
+          (funcall (-flip #'-) 3 2 1 10)
+              ⇒ 4
+          (funcall (-flip #'1+) 1)
+              ⇒ 2
+
+ -- Function: -rotate-args (n fn)
+     Return a function that calls FN with args rotated N places to the
+     right.  The returned function takes the same number of arguments as
+     FN, rotates the list of arguments N places to the right (left if N
+     is negative) just like ‘-rotate’ (*note -rotate::), and applies FN
+     to the result.
+
+     See also: ‘-flip’ (*note -flip::).
+
+          (funcall (-rotate-args -1 #'list) 1 2 3 4)
+              ⇒ (2 3 4 1)
+          (funcall (-rotate-args 1 #'-) 1 10 100)
+              ⇒ 89
+          (funcall (-rotate-args 2 #'list) 3 4 5 1 2)
+              ⇒ (1 2 3 4 5)
+
+ -- Function: -const (c)
+     Return a function that returns C ignoring any additional arguments.
+
+     In types: a -> b -> a
+
+          (funcall (-const 2) 1 3 "foo")
+              ⇒ 2
+          (mapcar (-const 1) '("a" "b" "c" "d"))
+              ⇒ (1 1 1 1)
+          (-sum (mapcar (-const 1) '("a" "b" "c" "d")))
+              ⇒ 4
+
+ -- Macro: -cut (&rest params)
+     Take n-ary function and n arguments and specialize some of them.
+     Arguments denoted by <> will be left unspecialized.
+
+     See SRFI-26 for detailed description.
+
+          (funcall (-cut list 1 <> 3 <> 5) 2 4)
+              ⇒ (1 2 3 4 5)
+          (-map (-cut funcall <> 5) `(1+ 1- ,(lambda (x) (/ 1.0 x))))
+              ⇒ (6 4 0.2)
+          (-map (-cut <> 1 2 3) '(list vector string))
+              ⇒ ((1 2 3) [1 2 3] "\1\2\3")
+
+ -- Function: -not (pred)
+     Return a predicate that negates the result of PRED.  The returned
+     predicate passes its arguments to PRED.  If PRED returns ‘nil’, the
+     result is non-‘nil’; otherwise the result is ‘nil’.
+
+     See also: ‘-andfn’ (*note -andfn::) and ‘-orfn’ (*note -orfn::).
+
+          (funcall (-not #'numberp) "5")
+              ⇒ t
+          (-sort (-not #'<) '(5 2 1 0 6))
+              ⇒ (6 5 2 1 0)
+          (-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8))
+              ⇒ (1 2 3 4)
+
+ -- Function: -orfn (&rest preds)
+     Return a predicate that returns the first non-‘nil’ result of
+     PREDS.  The returned predicate takes a variable number of
+     arguments, passes them to each predicate in PREDS in turn until one
+     of them returns non-‘nil’, and returns that non-‘nil’ result
+     without calling the remaining PREDS.  If all PREDS return ‘nil’, or
+     if no PREDS are given, the returned predicate returns ‘nil’.
+
+     See also: ‘-andfn’ (*note -andfn::) and ‘-not’ (*note -not::).
+
+          (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t))
+              ⇒ (1 nil t)
+          (funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe")
+              ⇒ 1
+          (funcall (-orfn #'= #'+) 1 1)
+              ⇒ t
+
+ -- Function: -andfn (&rest preds)
+     Return a predicate that returns non-‘nil’ if all PREDS do so.  The
+     returned predicate P takes a variable number of arguments and
+     passes them to each predicate in PREDS in turn.  If any one of
+     PREDS returns ‘nil’, P also returns ‘nil’ without calling the
+     remaining PREDS.  If all PREDS return non-‘nil’, P returns the last
+     such value.  If no PREDS are given, P always returns non-‘nil’.
+
+     See also: ‘-orfn’ (*note -orfn::) and ‘-not’ (*note -not::).
+
+          (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2))
+              ⇒ (1 2)
+          (mapcar (-andfn #'numberp #'1+) '(a 1 b 6))
+              ⇒ (nil 2 nil 7)
+          (funcall (-andfn #'= #'+) 1 1)
+              ⇒ 2
+
+ -- Function: -iteratefn (fn n)
+     Return a function FN composed N times with itself.
+
+     FN is a unary function.  If you need to use a function of higher
+     arity, use ‘-applify’ (*note -applify::) first to turn it into a
+     unary function.
+
+     With n = 0, this acts as identity function.
+
+     In types: (a -> a) -> Int -> a -> a.
+
+     This function satisfies the following law:
+
+     (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init
+     (1+ n))).
+
+          (funcall (-iteratefn (lambda (x) (* x x)) 3) 2)
+              ⇒ 256
+          (funcall (-iteratefn '1+ 3) 1)
+              ⇒ 4
+          (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5))
+              ⇒ (4 5)
+
+ -- Function: -fixfn (fn &optional equal-test halt-test)
+     Return a function that computes the (least) fixpoint of FN.
+
+     FN must be a unary function.  The returned lambda takes a single
+     argument, X, the initial value for the fixpoint iteration.  The
+     iteration halts when either of the following conditions is
+     satisfied:
+
+     1.  Iteration converges to the fixpoint, with equality being tested
+     using EQUAL-TEST.  If EQUAL-TEST is not specified, ‘equal’ is used.
+     For functions over the floating point numbers, it may be necessary
+     to provide an appropriate approximate comparison test.
+
+     2.  HALT-TEST returns a non-‘nil’ value.  HALT-TEST defaults to a
+     simple counter that returns ‘t’ after ‘-fixfn-max-iterations’, to
+     guard against infinite iteration.  Otherwise, HALT-TEST must be a
+     function that accepts a single argument, the current value of X,
+     and returns non-‘nil’ as long as iteration should continue.  In
+     this way, a more sophisticated convergence test may be supplied by
+     the caller.
+
+     The return value of the lambda is either the fixpoint or, if
+     iteration halted before converging, a cons with car ‘halted’ and
+     cdr the final output from HALT-TEST.
+
+     In types: (a -> a) -> a -> a.
+
+          (funcall (-fixfn #'cos #'approx=) 0.7)
+              ⇒ 0.7390851332151607
+          (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0)
+              ⇒ 1.8555845286409378
+          (funcall (-fixfn #'sin #'approx=) 0.1)
+              ⇒ (halted . t)
+
+ -- Function: -prodfn (&rest fns)
+     Return a function that applies each of FNS to each of a list of
+     arguments.
+
+     Takes a list of N functions and returns a function that takes a
+     list of length N, applying Ith function to Ith element of the input
+     list.  Returns a list of length N.
+
+     In types (for N=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d)
+
+     This function satisfies the following laws:
+
+     (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn
+     (-compose f f’) (-compose g g’) ...)
+
+     (-prodfn f g ...) = (-juxt (-compose f (-partial #’nth 0))
+     (-compose g (-partial #’nth 1)) ...)
+
+     (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose f
+     f’) (-compose g g’) ...)
+
+     (-compose (-partial #’nth n) (-prod f1 f2 ...)) = (-compose fn
+     (-partial #’nth n))
+
+          (funcall (-prodfn #'1+ #'1- #'number-to-string) '(1 2 3))
+              ⇒ (2 1 "3")
+          (-map (-prodfn #'1- #'1+) '((1 2) (3 4) (5 6)))
+              ⇒ ((0 3) (2 5) (4 7))
+          (apply #'+ (funcall (-prodfn #'length #'string-to-number) '((t) "5")))
+              ⇒ 6
+
+\1f
+File: dash.info,  Node: Development,  Next: FDL,  Prev: Functions,  Up: Top
+
+3 Development
+*************
+
+The Dash repository is hosted on GitHub at
+<https://github.com/magnars/dash.el>.
+
+* Menu:
+
+* Contribute::          How to contribute.
+* Contributors::        List of contributors.
+
+\1f
+File: dash.info,  Node: Contribute,  Next: Contributors,  Up: Development
+
+3.1 Contribute
+==============
+
+Yes, please do.  Pure functions in the list manipulation realm only,
+please.  There’s a suite of examples/tests in ‘dev/examples.el’, so
+remember to add tests for your additions, or they may get broken later.
+
+   Run the tests with ‘make check’.  Regenerate the docs with ‘make
+docs’.  Contributors are encouraged to install these commands as a Git
+pre-commit hook, so that the tests are always running and the docs are
+always in sync:
+
+     $ cp dev/pre-commit.sh .git/hooks/pre-commit
+
+   Oh, and don’t edit ‘README.md’ or ‘dash.texi’ directly, as they are
+auto-generated.  Instead, change their respective templates
+‘readme-template.md’ or ‘dash-template.texi’.
+
+   To ensure that Dash can be distributed with GNU ELPA or Emacs, we
+require that all contributors assign copyright to the Free Software
+Foundation.  For more on this, *note (emacs)Copyright Assignment::.
+
+\1f
+File: dash.info,  Node: Contributors,  Prev: Contribute,  Up: Development
+
+3.2 Contributors
+================
+
+   • Matus Goljer (https://github.com/Fuco1) contributed lots of
+     features and functions.
+   • Takafumi Arakaki (https://github.com/tkf) contributed ‘-group-by’.
+   • tali713 (https://github.com/tali713) is the author of ‘-applify’.
+   • Víctor M. Valenzuela (https://github.com/vemv) contributed
+     ‘-repeat’.
+   • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’.
+   • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’,
+     ‘-first-item’, and ‘-last-item’.
+   • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’,
+     ‘-when-let’, and ‘-insert-at’.
+   • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’,
+     ‘-product’, and ‘-same-items?’.
+   • Christina Whyte (https://github.com/kurisuwhyte) contributed
+     ‘-compose’.
+   • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’,
+     ‘-pad’, ‘-annotate’, ‘-zip-fill’, and a variadic version of ‘-zip’.
+   • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’
+     family use ‘-let’ destructuring and improved the script for
+     generating documentation.
+   • Mark Oteiza (https://github.com/holomorph) contributed ‘-iota’ and
+     the script to create an Info manual.
+   • Vasilij Schneidermann (https://github.com/wasamasa) contributed
+     ‘-some’.
+   • William West (https://github.com/occidens) made ‘-fixfn’ more
+     robust at handling floats.
+   • Cam Saul (https://github.com/camsaul) contributed ‘-some->’,
+     ‘-some->>’, and ‘-some-->’.
+   • Basil L. Contovounesios (https://github.com/basil-conto)
+     contributed ‘-common-prefix’, ‘-common-suffix’, and various other
+     improvements.
+   • Paul Pogonyshev (https://github.com/doublep) contributed ‘-each-r’
+     and ‘-each-r-while’.
+
+   Thanks!
+
+   New contributors are very welcome.  *Note Contribute::.
+
+\1f
+File: dash.info,  Node: FDL,  Next: GPL,  Prev: Development,  Up: Top
+
+Appendix A GNU Free Documentation License
+*****************************************
+
+                     Version 1.3, 3 November 2008
+
+     Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
+     <https://fsf.org/>
+
+     Everyone is permitted to copy and distribute verbatim copies
+     of this license document, but changing it is not allowed.
+
+  0. PREAMBLE
+
+     The purpose of this License is to make a manual, textbook, or other
+     functional and useful document “free” in the sense of freedom: to
+     assure everyone the effective freedom to copy and redistribute it,
+     with or without modifying it, either commercially or
+     noncommercially.  Secondarily, this License preserves for the
+     author and publisher a way to get credit for their work, while not
+     being considered responsible for modifications made by others.
+
+     This License is a kind of “copyleft”, which means that derivative
+     works of the document must themselves be free in the same sense.
+     It complements the GNU General Public License, which is a copyleft
+     license designed for free software.
+
+     We have designed this License in order to use it for manuals for
+     free software, because free software needs free documentation: a
+     free program should come with manuals providing the same freedoms
+     that the software does.  But this License is not limited to
+     software manuals; it can be used for any textual work, regardless
+     of subject matter or whether it is published as a printed book.  We
+     recommend this License principally for works whose purpose is
+     instruction or reference.
+
+  1. APPLICABILITY AND DEFINITIONS
+
+     This License applies to any manual or other work, in any medium,
+     that contains a notice placed by the copyright holder saying it can
+     be distributed under the terms of this License.  Such a notice
+     grants a world-wide, royalty-free license, unlimited in duration,
+     to use that work under the conditions stated herein.  The
+     “Document”, below, refers to any such manual or work.  Any member
+     of the public is a licensee, and is addressed as “you”.  You accept
+     the license if you copy, modify or distribute the work in a way
+     requiring permission under copyright law.
+
+     A “Modified Version” of the Document means any work containing the
+     Document or a portion of it, either copied verbatim, or with
+     modifications and/or translated into another language.
+
+     A “Secondary Section” is a named appendix or a front-matter section
+     of the Document that deals exclusively with the relationship of the
+     publishers or authors of the Document to the Document’s overall
+     subject (or to related matters) and contains nothing that could
+     fall directly within that overall subject.  (Thus, if the Document
+     is in part a textbook of mathematics, a Secondary Section may not
+     explain any mathematics.)  The relationship could be a matter of
+     historical connection with the subject or with related matters, or
+     of legal, commercial, philosophical, ethical or political position
+     regarding them.
+
+     The “Invariant Sections” are certain Secondary Sections whose
+     titles are designated, as being those of Invariant Sections, in the
+     notice that says that the Document is released under this License.
+     If a section does not fit the above definition of Secondary then it
+     is not allowed to be designated as Invariant.  The Document may
+     contain zero Invariant Sections.  If the Document does not identify
+     any Invariant Sections then there are none.
+
+     The “Cover Texts” are certain short passages of text that are
+     listed, as Front-Cover Texts or Back-Cover Texts, in the notice
+     that says that the Document is released under this License.  A
+     Front-Cover Text may be at most 5 words, and a Back-Cover Text may
+     be at most 25 words.
+
+     A “Transparent” copy of the Document means a machine-readable copy,
+     represented in a format whose specification is available to the
+     general public, that is suitable for revising the document
+     straightforwardly with generic text editors or (for images composed
+     of pixels) generic paint programs or (for drawings) some widely
+     available drawing editor, and that is suitable for input to text
+     formatters or for automatic translation to a variety of formats
+     suitable for input to text formatters.  A copy made in an otherwise
+     Transparent file format whose markup, or absence of markup, has
+     been arranged to thwart or discourage subsequent modification by
+     readers is not Transparent.  An image format is not Transparent if
+     used for any substantial amount of text.  A copy that is not
+     “Transparent” is called “Opaque”.
+
+     Examples of suitable formats for Transparent copies include plain
+     ASCII without markup, Texinfo input format, LaTeX input format,
+     SGML or XML using a publicly available DTD, and standard-conforming
+     simple HTML, PostScript or PDF designed for human modification.
+     Examples of transparent image formats include PNG, XCF and JPG.
+     Opaque formats include proprietary formats that can be read and
+     edited only by proprietary word processors, SGML or XML for which
+     the DTD and/or processing tools are not generally available, and
+     the machine-generated HTML, PostScript or PDF produced by some word
+     processors for output purposes only.
+
+     The “Title Page” means, for a printed book, the title page itself,
+     plus such following pages as are needed to hold, legibly, the
+     material this License requires to appear in the title page.  For
+     works in formats which do not have any title page as such, “Title
+     Page” means the text near the most prominent appearance of the
+     work’s title, preceding the beginning of the body of the text.
+
+     The “publisher” means any person or entity that distributes copies
+     of the Document to the public.
+
+     A section “Entitled XYZ” means a named subunit of the Document
+     whose title either is precisely XYZ or contains XYZ in parentheses
+     following text that translates XYZ in another language.  (Here XYZ
+     stands for a specific section name mentioned below, such as
+     “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.)
+     To “Preserve the Title” of such a section when you modify the
+     Document means that it remains a section “Entitled XYZ” according
+     to this definition.
+
+     The Document may include Warranty Disclaimers next to the notice
+     which states that this License applies to the Document.  These
+     Warranty Disclaimers are considered to be included by reference in
+     this License, but only as regards disclaiming warranties: any other
+     implication that these Warranty Disclaimers may have is void and
+     has no effect on the meaning of this License.
+
+  2. VERBATIM COPYING
+
+     You may copy and distribute the Document in any medium, either
+     commercially or noncommercially, provided that this License, the
+     copyright notices, and the license notice saying this License
+     applies to the Document are reproduced in all copies, and that you
+     add no other conditions whatsoever to those of this License.  You
+     may not use technical measures to obstruct or control the reading
+     or further copying of the copies you make or distribute.  However,
+     you may accept compensation in exchange for copies.  If you
+     distribute a large enough number of copies you must also follow the
+     conditions in section 3.
+
+     You may also lend copies, under the same conditions stated above,
+     and you may publicly display copies.
+
+  3. COPYING IN QUANTITY
+
+     If you publish printed copies (or copies in media that commonly
+     have printed covers) of the Document, numbering more than 100, and
+     the Document’s license notice requires Cover Texts, you must
+     enclose the copies in covers that carry, clearly and legibly, all
+     these Cover Texts: Front-Cover Texts on the front cover, and
+     Back-Cover Texts on the back cover.  Both covers must also clearly
+     and legibly identify you as the publisher of these copies.  The
+     front cover must present the full title with all words of the title
+     equally prominent and visible.  You may add other material on the
+     covers in addition.  Copying with changes limited to the covers, as
+     long as they preserve the title of the Document and satisfy these
+     conditions, can be treated as verbatim copying in other respects.
+
+     If the required texts for either cover are too voluminous to fit
+     legibly, you should put the first ones listed (as many as fit
+     reasonably) on the actual cover, and continue the rest onto
+     adjacent pages.
+
+     If you publish or distribute Opaque copies of the Document
+     numbering more than 100, you must either include a machine-readable
+     Transparent copy along with each Opaque copy, or state in or with
+     each Opaque copy a computer-network location from which the general
+     network-using public has access to download using public-standard
+     network protocols a complete Transparent copy of the Document, free
+     of added material.  If you use the latter option, you must take
+     reasonably prudent steps, when you begin distribution of Opaque
+     copies in quantity, to ensure that this Transparent copy will
+     remain thus accessible at the stated location until at least one
+     year after the last time you distribute an Opaque copy (directly or
+     through your agents or retailers) of that edition to the public.
+
+     It is requested, but not required, that you contact the authors of
+     the Document well before redistributing any large number of copies,
+     to give them a chance to provide you with an updated version of the
+     Document.
+
+  4. MODIFICATIONS
+
+     You may copy and distribute a Modified Version of the Document
+     under the conditions of sections 2 and 3 above, provided that you
+     release the Modified Version under precisely this License, with the
+     Modified Version filling the role of the Document, thus licensing
+     distribution and modification of the Modified Version to whoever
+     possesses a copy of it.  In addition, you must do these things in
+     the Modified Version:
+
+       A. Use in the Title Page (and on the covers, if any) a title
+          distinct from that of the Document, and from those of previous
+          versions (which should, if there were any, be listed in the
+          History section of the Document).  You may use the same title
+          as a previous version if the original publisher of that
+          version gives permission.
+
+       B. List on the Title Page, as authors, one or more persons or
+          entities responsible for authorship of the modifications in
+          the Modified Version, together with at least five of the
+          principal authors of the Document (all of its principal
+          authors, if it has fewer than five), unless they release you
+          from this requirement.
+
+       C. State on the Title page the name of the publisher of the
+          Modified Version, as the publisher.
+
+       D. Preserve all the copyright notices of the Document.
+
+       E. Add an appropriate copyright notice for your modifications
+          adjacent to the other copyright notices.
+
+       F. Include, immediately after the copyright notices, a license
+          notice giving the public permission to use the Modified
+          Version under the terms of this License, in the form shown in
+          the Addendum below.
+
+       G. Preserve in that license notice the full lists of Invariant
+          Sections and required Cover Texts given in the Document’s
+          license notice.
+
+       H. Include an unaltered copy of this License.
+
+       I. Preserve the section Entitled “History”, Preserve its Title,
+          and add to it an item stating at least the title, year, new
+          authors, and publisher of the Modified Version as given on the
+          Title Page.  If there is no section Entitled “History” in the
+          Document, create one stating the title, year, authors, and
+          publisher of the Document as given on its Title Page, then add
+          an item describing the Modified Version as stated in the
+          previous sentence.
+
+       J. Preserve the network location, if any, given in the Document
+          for public access to a Transparent copy of the Document, and
+          likewise the network locations given in the Document for
+          previous versions it was based on.  These may be placed in the
+          “History” section.  You may omit a network location for a work
+          that was published at least four years before the Document
+          itself, or if the original publisher of the version it refers
+          to gives permission.
+
+       K. For any section Entitled “Acknowledgements” or “Dedications”,
+          Preserve the Title of the section, and preserve in the section
+          all the substance and tone of each of the contributor
+          acknowledgements and/or dedications given therein.
+
+       L. Preserve all the Invariant Sections of the Document, unaltered
+          in their text and in their titles.  Section numbers or the
+          equivalent are not considered part of the section titles.
+
+       M. Delete any section Entitled “Endorsements”.  Such a section
+          may not be included in the Modified Version.
+
+       N. Do not retitle any existing section to be Entitled
+          “Endorsements” or to conflict in title with any Invariant
+          Section.
+
+       O. Preserve any Warranty Disclaimers.
+
+     If the Modified Version includes new front-matter sections or
+     appendices that qualify as Secondary Sections and contain no
+     material copied from the Document, you may at your option designate
+     some or all of these sections as invariant.  To do this, add their
+     titles to the list of Invariant Sections in the Modified Version’s
+     license notice.  These titles must be distinct from any other
+     section titles.
+
+     You may add a section Entitled “Endorsements”, provided it contains
+     nothing but endorsements of your Modified Version by various
+     parties—for example, statements of peer review or that the text has
+     been approved by an organization as the authoritative definition of
+     a standard.
+
+     You may add a passage of up to five words as a Front-Cover Text,
+     and a passage of up to 25 words as a Back-Cover Text, to the end of
+     the list of Cover Texts in the Modified Version.  Only one passage
+     of Front-Cover Text and one of Back-Cover Text may be added by (or
+     through arrangements made by) any one entity.  If the Document
+     already includes a cover text for the same cover, previously added
+     by you or by arrangement made by the same entity you are acting on
+     behalf of, you may not add another; but you may replace the old
+     one, on explicit permission from the previous publisher that added
+     the old one.
+
+     The author(s) and publisher(s) of the Document do not by this
+     License give permission to use their names for publicity for or to
+     assert or imply endorsement of any Modified Version.
+
+  5. COMBINING DOCUMENTS
+
+     You may combine the Document with other documents released under
+     this License, under the terms defined in section 4 above for
+     modified versions, provided that you include in the combination all
+     of the Invariant Sections of all of the original documents,
+     unmodified, and list them all as Invariant Sections of your
+     combined work in its license notice, and that you preserve all
+     their Warranty Disclaimers.
+
+     The combined work need only contain one copy of this License, and
+     multiple identical Invariant Sections may be replaced with a single
+     copy.  If there are multiple Invariant Sections with the same name
+     but different contents, make the title of each such section unique
+     by adding at the end of it, in parentheses, the name of the
+     original author or publisher of that section if known, or else a
+     unique number.  Make the same adjustment to the section titles in
+     the list of Invariant Sections in the license notice of the
+     combined work.
+
+     In the combination, you must combine any sections Entitled
+     “History” in the various original documents, forming one section
+     Entitled “History”; likewise combine any sections Entitled
+     “Acknowledgements”, and any sections Entitled “Dedications”.  You
+     must delete all sections Entitled “Endorsements.”
+
+  6. COLLECTIONS OF DOCUMENTS
+
+     You may make a collection consisting of the Document and other
+     documents released under this License, and replace the individual
+     copies of this License in the various documents with a single copy
+     that is included in the collection, provided that you follow the
+     rules of this License for verbatim copying of each of the documents
+     in all other respects.
+
+     You may extract a single document from such a collection, and
+     distribute it individually under this License, provided you insert
+     a copy of this License into the extracted document, and follow this
+     License in all other respects regarding verbatim copying of that
+     document.
+
+  7. AGGREGATION WITH INDEPENDENT WORKS
+
+     A compilation of the Document or its derivatives with other
+     separate and independent documents or works, in or on a volume of a
+     storage or distribution medium, is called an “aggregate” if the
+     copyright resulting from the compilation is not used to limit the
+     legal rights of the compilation’s users beyond what the individual
+     works permit.  When the Document is included in an aggregate, this
+     License does not apply to the other works in the aggregate which
+     are not themselves derivative works of the Document.
+
+     If the Cover Text requirement of section 3 is applicable to these
+     copies of the Document, then if the Document is less than one half
+     of the entire aggregate, the Document’s Cover Texts may be placed
+     on covers that bracket the Document within the aggregate, or the
+     electronic equivalent of covers if the Document is in electronic
+     form.  Otherwise they must appear on printed covers that bracket
+     the whole aggregate.
+
+  8. TRANSLATION
+
+     Translation is considered a kind of modification, so you may
+     distribute translations of the Document under the terms of section
+     4.  Replacing Invariant Sections with translations requires special
+     permission from their copyright holders, but you may include
+     translations of some or all Invariant Sections in addition to the
+     original versions of these Invariant Sections.  You may include a
+     translation of this License, and all the license notices in the
+     Document, and any Warranty Disclaimers, provided that you also
+     include the original English version of this License and the
+     original versions of those notices and disclaimers.  In case of a
+     disagreement between the translation and the original version of
+     this License or a notice or disclaimer, the original version will
+     prevail.
+
+     If a section in the Document is Entitled “Acknowledgements”,
+     “Dedications”, or “History”, the requirement (section 4) to
+     Preserve its Title (section 1) will typically require changing the
+     actual title.
+
+  9. TERMINATION
+
+     You may not copy, modify, sublicense, or distribute the Document
+     except as expressly provided under this License.  Any attempt
+     otherwise to copy, modify, sublicense, or distribute it is void,
+     and will automatically terminate your rights under this License.
+
+     However, if you cease all violation of this License, then your
+     license from a particular copyright holder is reinstated (a)
+     provisionally, unless and until the copyright holder explicitly and
+     finally terminates your license, and (b) permanently, if the
+     copyright holder fails to notify you of the violation by some
+     reasonable means prior to 60 days after the cessation.
+
+     Moreover, your license from a particular copyright holder is
+     reinstated permanently if the copyright holder notifies you of the
+     violation by some reasonable means, this is the first time you have
+     received notice of violation of this License (for any work) from
+     that copyright holder, and you cure the violation prior to 30 days
+     after your receipt of the notice.
+
+     Termination of your rights under this section does not terminate
+     the licenses of parties who have received copies or rights from you
+     under this License.  If your rights have been terminated and not
+     permanently reinstated, receipt of a copy of some or all of the
+     same material does not give you any rights to use it.
+
+  10. FUTURE REVISIONS OF THIS LICENSE
+
+     The Free Software Foundation may publish new, revised versions of
+     the GNU Free Documentation License from time to time.  Such new
+     versions will be similar in spirit to the present version, but may
+     differ in detail to address new problems or concerns.  See
+     <https://www.gnu.org/licenses/>.
+
+     Each version of the License is given a distinguishing version
+     number.  If the Document specifies that a particular numbered
+     version of this License “or any later version” applies to it, you
+     have the option of following the terms and conditions either of
+     that specified version or of any later version that has been
+     published (not as a draft) by the Free Software Foundation.  If the
+     Document does not specify a version number of this License, you may
+     choose any version ever published (not as a draft) by the Free
+     Software Foundation.  If the Document specifies that a proxy can
+     decide which future versions of this License can be used, that
+     proxy’s public statement of acceptance of a version permanently
+     authorizes you to choose that version for the Document.
+
+  11. RELICENSING
+
+     “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any
+     World Wide Web server that publishes copyrightable works and also
+     provides prominent facilities for anybody to edit those works.  A
+     public wiki that anybody can edit is an example of such a server.
+     A “Massive Multiauthor Collaboration” (or “MMC”) contained in the
+     site means any set of copyrightable works thus published on the MMC
+     site.
+
+     “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0
+     license published by Creative Commons Corporation, a not-for-profit
+     corporation with a principal place of business in San Francisco,
+     California, as well as future copyleft versions of that license
+     published by that same organization.
+
+     “Incorporate” means to publish or republish a Document, in whole or
+     in part, as part of another Document.
+
+     An MMC is “eligible for relicensing” if it is licensed under this
+     License, and if all works that were first published under this
+     License somewhere other than this MMC, and subsequently
+     incorporated in whole or in part into the MMC, (1) had no cover
+     texts or invariant sections, and (2) were thus incorporated prior
+     to November 1, 2008.
+
+     The operator of an MMC Site may republish an MMC contained in the
+     site under CC-BY-SA on the same site at any time before August 1,
+     2009, provided the MMC is eligible for relicensing.
+
+ADDENDUM: How to use this License for your documents
+====================================================
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and license
+notices just after the title page:
+
+       Copyright (C)  YEAR  YOUR NAME.
+       Permission is granted to copy, distribute and/or modify this document
+       under the terms of the GNU Free Documentation License, Version 1.3
+       or any later version published by the Free Software Foundation;
+       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+       Texts.  A copy of the license is included in the section entitled ``GNU
+       Free Documentation License''.
+
+   If you have Invariant Sections, Front-Cover Texts and Back-Cover
+Texts, replace the “with...Texts.” line with this:
+
+         with the Invariant Sections being LIST THEIR TITLES, with
+         the Front-Cover Texts being LIST, and with the Back-Cover Texts
+         being LIST.
+
+   If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+   If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of free
+software license, such as the GNU General Public License, to permit
+their use in free software.
+
+\1f
+File: dash.info,  Node: GPL,  Next: Index,  Prev: FDL,  Up: Top
+
+Appendix B GNU General Public License
+*************************************
+
+                        Version 3, 29 June 2007
+
+     Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
+
+     Everyone is permitted to copy and distribute verbatim copies of this
+     license document, but changing it is not allowed.
+
+Preamble
+========
+
+The GNU General Public License is a free, copyleft license for software
+and other kinds of works.
+
+   The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program—to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+   When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+   To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+   For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+   Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+   For the developers’ and authors’ protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users’ and
+authors’ sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+   Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users’ freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+   Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+   The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS
+====================
+
+  0. Definitions.
+
+     “This License” refers to version 3 of the GNU General Public
+     License.
+
+     “Copyright” also means copyright-like laws that apply to other
+     kinds of works, such as semiconductor masks.
+
+     “The Program” refers to any copyrightable work licensed under this
+     License.  Each licensee is addressed as “you”.  “Licensees” and
+     “recipients” may be individuals or organizations.
+
+     To “modify” a work means to copy from or adapt all or part of the
+     work in a fashion requiring copyright permission, other than the
+     making of an exact copy.  The resulting work is called a “modified
+     version” of the earlier work or a work “based on” the earlier work.
+
+     A “covered work” means either the unmodified Program or a work
+     based on the Program.
+
+     To “propagate” a work means to do anything with it that, without
+     permission, would make you directly or secondarily liable for
+     infringement under applicable copyright law, except executing it on
+     a computer or modifying a private copy.  Propagation includes
+     copying, distribution (with or without modification), making
+     available to the public, and in some countries other activities as
+     well.
+
+     To “convey” a work means any kind of propagation that enables other
+     parties to make or receive copies.  Mere interaction with a user
+     through a computer network, with no transfer of a copy, is not
+     conveying.
+
+     An interactive user interface displays “Appropriate Legal Notices”
+     to the extent that it includes a convenient and prominently visible
+     feature that (1) displays an appropriate copyright notice, and (2)
+     tells the user that there is no warranty for the work (except to
+     the extent that warranties are provided), that licensees may convey
+     the work under this License, and how to view a copy of this
+     License.  If the interface presents a list of user commands or
+     options, such as a menu, a prominent item in the list meets this
+     criterion.
+
+  1. Source Code.
+
+     The “source code” for a work means the preferred form of the work
+     for making modifications to it.  “Object code” means any non-source
+     form of a work.
+
+     A “Standard Interface” means an interface that either is an
+     official standard defined by a recognized standards body, or, in
+     the case of interfaces specified for a particular programming
+     language, one that is widely used among developers working in that
+     language.
+
+     The “System Libraries” of an executable work include anything,
+     other than the work as a whole, that (a) is included in the normal
+     form of packaging a Major Component, but which is not part of that
+     Major Component, and (b) serves only to enable use of the work with
+     that Major Component, or to implement a Standard Interface for
+     which an implementation is available to the public in source code
+     form.  A “Major Component”, in this context, means a major
+     essential component (kernel, window system, and so on) of the
+     specific operating system (if any) on which the executable work
+     runs, or a compiler used to produce the work, or an object code
+     interpreter used to run it.
+
+     The “Corresponding Source” for a work in object code form means all
+     the source code needed to generate, install, and (for an executable
+     work) run the object code and to modify the work, including scripts
+     to control those activities.  However, it does not include the
+     work’s System Libraries, or general-purpose tools or generally
+     available free programs which are used unmodified in performing
+     those activities but which are not part of the work.  For example,
+     Corresponding Source includes interface definition files associated
+     with source files for the work, and the source code for shared
+     libraries and dynamically linked subprograms that the work is
+     specifically designed to require, such as by intimate data
+     communication or control flow between those subprograms and other
+     parts of the work.
+
+     The Corresponding Source need not include anything that users can
+     regenerate automatically from other parts of the Corresponding
+     Source.
+
+     The Corresponding Source for a work in source code form is that
+     same work.
+
+  2. Basic Permissions.
+
+     All rights granted under this License are granted for the term of
+     copyright on the Program, and are irrevocable provided the stated
+     conditions are met.  This License explicitly affirms your unlimited
+     permission to run the unmodified Program.  The output from running
+     a covered work is covered by this License only if the output, given
+     its content, constitutes a covered work.  This License acknowledges
+     your rights of fair use or other equivalent, as provided by
+     copyright law.
+
+     You may make, run and propagate covered works that you do not
+     convey, without conditions so long as your license otherwise
+     remains in force.  You may convey covered works to others for the
+     sole purpose of having them make modifications exclusively for you,
+     or provide you with facilities for running those works, provided
+     that you comply with the terms of this License in conveying all
+     material for which you do not control copyright.  Those thus making
+     or running the covered works for you must do so exclusively on your
+     behalf, under your direction and control, on terms that prohibit
+     them from making any copies of your copyrighted material outside
+     their relationship with you.
+
+     Conveying under any other circumstances is permitted solely under
+     the conditions stated below.  Sublicensing is not allowed; section
+     10 makes it unnecessary.
+
+  3. Protecting Users’ Legal Rights From Anti-Circumvention Law.
+
+     No covered work shall be deemed part of an effective technological
+     measure under any applicable law fulfilling obligations under
+     article 11 of the WIPO copyright treaty adopted on 20 December
+     1996, or similar laws prohibiting or restricting circumvention of
+     such measures.
+
+     When you convey a covered work, you waive any legal power to forbid
+     circumvention of technological measures to the extent such
+     circumvention is effected by exercising rights under this License
+     with respect to the covered work, and you disclaim any intention to
+     limit operation or modification of the work as a means of
+     enforcing, against the work’s users, your or third parties’ legal
+     rights to forbid circumvention of technological measures.
+
+  4. Conveying Verbatim Copies.
+
+     You may convey verbatim copies of the Program’s source code as you
+     receive it, in any medium, provided that you conspicuously and
+     appropriately publish on each copy an appropriate copyright notice;
+     keep intact all notices stating that this License and any
+     non-permissive terms added in accord with section 7 apply to the
+     code; keep intact all notices of the absence of any warranty; and
+     give all recipients a copy of this License along with the Program.
+
+     You may charge any price or no price for each copy that you convey,
+     and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+     You may convey a work based on the Program, or the modifications to
+     produce it from the Program, in the form of source code under the
+     terms of section 4, provided that you also meet all of these
+     conditions:
+
+       a. The work must carry prominent notices stating that you
+          modified it, and giving a relevant date.
+
+       b. The work must carry prominent notices stating that it is
+          released under this License and any conditions added under
+          section 7.  This requirement modifies the requirement in
+          section 4 to “keep intact all notices”.
+
+       c. You must license the entire work, as a whole, under this
+          License to anyone who comes into possession of a copy.  This
+          License will therefore apply, along with any applicable
+          section 7 additional terms, to the whole of the work, and all
+          its parts, regardless of how they are packaged.  This License
+          gives no permission to license the work in any other way, but
+          it does not invalidate such permission if you have separately
+          received it.
+
+       d. If the work has interactive user interfaces, each must display
+          Appropriate Legal Notices; however, if the Program has
+          interactive interfaces that do not display Appropriate Legal
+          Notices, your work need not make them do so.
+
+     A compilation of a covered work with other separate and independent
+     works, which are not by their nature extensions of the covered
+     work, and which are not combined with it such as to form a larger
+     program, in or on a volume of a storage or distribution medium, is
+     called an “aggregate” if the compilation and its resulting
+     copyright are not used to limit the access or legal rights of the
+     compilation’s users beyond what the individual works permit.
+     Inclusion of a covered work in an aggregate does not cause this
+     License to apply to the other parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+     You may convey a covered work in object code form under the terms
+     of sections 4 and 5, provided that you also convey the
+     machine-readable Corresponding Source under the terms of this
+     License, in one of these ways:
+
+       a. Convey the object code in, or embodied in, a physical product
+          (including a physical distribution medium), accompanied by the
+          Corresponding Source fixed on a durable physical medium
+          customarily used for software interchange.
+
+       b. Convey the object code in, or embodied in, a physical product
+          (including a physical distribution medium), accompanied by a
+          written offer, valid for at least three years and valid for as
+          long as you offer spare parts or customer support for that
+          product model, to give anyone who possesses the object code
+          either (1) a copy of the Corresponding Source for all the
+          software in the product that is covered by this License, on a
+          durable physical medium customarily used for software
+          interchange, for a price no more than your reasonable cost of
+          physically performing this conveying of source, or (2) access
+          to copy the Corresponding Source from a network server at no
+          charge.
+
+       c. Convey individual copies of the object code with a copy of the
+          written offer to provide the Corresponding Source.  This
+          alternative is allowed only occasionally and noncommercially,
+          and only if you received the object code with such an offer,
+          in accord with subsection 6b.
+
+       d. Convey the object code by offering access from a designated
+          place (gratis or for a charge), and offer equivalent access to
+          the Corresponding Source in the same way through the same
+          place at no further charge.  You need not require recipients
+          to copy the Corresponding Source along with the object code.
+          If the place to copy the object code is a network server, the
+          Corresponding Source may be on a different server (operated by
+          you or a third party) that supports equivalent copying
+          facilities, provided you maintain clear directions next to the
+          object code saying where to find the Corresponding Source.
+          Regardless of what server hosts the Corresponding Source, you
+          remain obligated to ensure that it is available for as long as
+          needed to satisfy these requirements.
+
+       e. Convey the object code using peer-to-peer transmission,
+          provided you inform other peers where the object code and
+          Corresponding Source of the work are being offered to the
+          general public at no charge under subsection 6d.
+
+     A separable portion of the object code, whose source code is
+     excluded from the Corresponding Source as a System Library, need
+     not be included in conveying the object code work.
+
+     A “User Product” is either (1) a “consumer product”, which means
+     any tangible personal property which is normally used for personal,
+     family, or household purposes, or (2) anything designed or sold for
+     incorporation into a dwelling.  In determining whether a product is
+     a consumer product, doubtful cases shall be resolved in favor of
+     coverage.  For a particular product received by a particular user,
+     “normally used” refers to a typical or common use of that class of
+     product, regardless of the status of the particular user or of the
+     way in which the particular user actually uses, or expects or is
+     expected to use, the product.  A product is a consumer product
+     regardless of whether the product has substantial commercial,
+     industrial or non-consumer uses, unless such uses represent the
+     only significant mode of use of the product.
+
+     “Installation Information” for a User Product means any methods,
+     procedures, authorization keys, or other information required to
+     install and execute modified versions of a covered work in that
+     User Product from a modified version of its Corresponding Source.
+     The information must suffice to ensure that the continued
+     functioning of the modified object code is in no case prevented or
+     interfered with solely because modification has been made.
+
+     If you convey an object code work under this section in, or with,
+     or specifically for use in, a User Product, and the conveying
+     occurs as part of a transaction in which the right of possession
+     and use of the User Product is transferred to the recipient in
+     perpetuity or for a fixed term (regardless of how the transaction
+     is characterized), the Corresponding Source conveyed under this
+     section must be accompanied by the Installation Information.  But
+     this requirement does not apply if neither you nor any third party
+     retains the ability to install modified object code on the User
+     Product (for example, the work has been installed in ROM).
+
+     The requirement to provide Installation Information does not
+     include a requirement to continue to provide support service,
+     warranty, or updates for a work that has been modified or installed
+     by the recipient, or for the User Product in which it has been
+     modified or installed.  Access to a network may be denied when the
+     modification itself materially and adversely affects the operation
+     of the network or violates the rules and protocols for
+     communication across the network.
+
+     Corresponding Source conveyed, and Installation Information
+     provided, in accord with this section must be in a format that is
+     publicly documented (and with an implementation available to the
+     public in source code form), and must require no special password
+     or key for unpacking, reading or copying.
+
+  7. Additional Terms.
+
+     “Additional permissions” are terms that supplement the terms of
+     this License by making exceptions from one or more of its
+     conditions.  Additional permissions that are applicable to the
+     entire Program shall be treated as though they were included in
+     this License, to the extent that they are valid under applicable
+     law.  If additional permissions apply only to part of the Program,
+     that part may be used separately under those permissions, but the
+     entire Program remains governed by this License without regard to
+     the additional permissions.
+
+     When you convey a copy of a covered work, you may at your option
+     remove any additional permissions from that copy, or from any part
+     of it.  (Additional permissions may be written to require their own
+     removal in certain cases when you modify the work.)  You may place
+     additional permissions on material, added by you to a covered work,
+     for which you have or can give appropriate copyright permission.
+
+     Notwithstanding any other provision of this License, for material
+     you add to a covered work, you may (if authorized by the copyright
+     holders of that material) supplement the terms of this License with
+     terms:
+
+       a. Disclaiming warranty or limiting liability differently from
+          the terms of sections 15 and 16 of this License; or
+
+       b. Requiring preservation of specified reasonable legal notices
+          or author attributions in that material or in the Appropriate
+          Legal Notices displayed by works containing it; or
+
+       c. Prohibiting misrepresentation of the origin of that material,
+          or requiring that modified versions of such material be marked
+          in reasonable ways as different from the original version; or
+
+       d. Limiting the use for publicity purposes of names of licensors
+          or authors of the material; or
+
+       e. Declining to grant rights under trademark law for use of some
+          trade names, trademarks, or service marks; or
+
+       f. Requiring indemnification of licensors and authors of that
+          material by anyone who conveys the material (or modified
+          versions of it) with contractual assumptions of liability to
+          the recipient, for any liability that these contractual
+          assumptions directly impose on those licensors and authors.
+
+     All other non-permissive additional terms are considered “further
+     restrictions” within the meaning of section 10.  If the Program as
+     you received it, or any part of it, contains a notice stating that
+     it is governed by this License along with a term that is a further
+     restriction, you may remove that term.  If a license document
+     contains a further restriction but permits relicensing or conveying
+     under this License, you may add to a covered work material governed
+     by the terms of that license document, provided that the further
+     restriction does not survive such relicensing or conveying.
+
+     If you add terms to a covered work in accord with this section, you
+     must place, in the relevant source files, a statement of the
+     additional terms that apply to those files, or a notice indicating
+     where to find the applicable terms.
+
+     Additional terms, permissive or non-permissive, may be stated in
+     the form of a separately written license, or stated as exceptions;
+     the above requirements apply either way.
+
+  8. Termination.
+
+     You may not propagate or modify a covered work except as expressly
+     provided under this License.  Any attempt otherwise to propagate or
+     modify it is void, and will automatically terminate your rights
+     under this License (including any patent licenses granted under the
+     third paragraph of section 11).
+
+     However, if you cease all violation of this License, then your
+     license from a particular copyright holder is reinstated (a)
+     provisionally, unless and until the copyright holder explicitly and
+     finally terminates your license, and (b) permanently, if the
+     copyright holder fails to notify you of the violation by some
+     reasonable means prior to 60 days after the cessation.
+
+     Moreover, your license from a particular copyright holder is
+     reinstated permanently if the copyright holder notifies you of the
+     violation by some reasonable means, this is the first time you have
+     received notice of violation of this License (for any work) from
+     that copyright holder, and you cure the violation prior to 30 days
+     after your receipt of the notice.
+
+     Termination of your rights under this section does not terminate
+     the licenses of parties who have received copies or rights from you
+     under this License.  If your rights have been terminated and not
+     permanently reinstated, you do not qualify to receive new licenses
+     for the same material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+     You are not required to accept this License in order to receive or
+     run a copy of the Program.  Ancillary propagation of a covered work
+     occurring solely as a consequence of using peer-to-peer
+     transmission to receive a copy likewise does not require
+     acceptance.  However, nothing other than this License grants you
+     permission to propagate or modify any covered work.  These actions
+     infringe copyright if you do not accept this License.  Therefore,
+     by modifying or propagating a covered work, you indicate your
+     acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+     Each time you convey a covered work, the recipient automatically
+     receives a license from the original licensors, to run, modify and
+     propagate that work, subject to this License.  You are not
+     responsible for enforcing compliance by third parties with this
+     License.
+
+     An “entity transaction” is a transaction transferring control of an
+     organization, or substantially all assets of one, or subdividing an
+     organization, or merging organizations.  If propagation of a
+     covered work results from an entity transaction, each party to that
+     transaction who receives a copy of the work also receives whatever
+     licenses to the work the party’s predecessor in interest had or
+     could give under the previous paragraph, plus a right to possession
+     of the Corresponding Source of the work from the predecessor in
+     interest, if the predecessor has it or can get it with reasonable
+     efforts.
+
+     You may not impose any further restrictions on the exercise of the
+     rights granted or affirmed under this License.  For example, you
+     may not impose a license fee, royalty, or other charge for exercise
+     of rights granted under this License, and you may not initiate
+     litigation (including a cross-claim or counterclaim in a lawsuit)
+     alleging that any patent claim is infringed by making, using,
+     selling, offering for sale, or importing the Program or any portion
+     of it.
+
+  11. Patents.
+
+     A “contributor” is a copyright holder who authorizes use under this
+     License of the Program or a work on which the Program is based.
+     The work thus licensed is called the contributor’s “contributor
+     version”.
+
+     A contributor’s “essential patent claims” are all patent claims
+     owned or controlled by the contributor, whether already acquired or
+     hereafter acquired, that would be infringed by some manner,
+     permitted by this License, of making, using, or selling its
+     contributor version, but do not include claims that would be
+     infringed only as a consequence of further modification of the
+     contributor version.  For purposes of this definition, “control”
+     includes the right to grant patent sublicenses in a manner
+     consistent with the requirements of this License.
+
+     Each contributor grants you a non-exclusive, worldwide,
+     royalty-free patent license under the contributor’s essential
+     patent claims, to make, use, sell, offer for sale, import and
+     otherwise run, modify and propagate the contents of its contributor
+     version.
+
+     In the following three paragraphs, a “patent license” is any
+     express agreement or commitment, however denominated, not to
+     enforce a patent (such as an express permission to practice a
+     patent or covenant not to sue for patent infringement).  To “grant”
+     such a patent license to a party means to make such an agreement or
+     commitment not to enforce a patent against the party.
+
+     If you convey a covered work, knowingly relying on a patent
+     license, and the Corresponding Source of the work is not available
+     for anyone to copy, free of charge and under the terms of this
+     License, through a publicly available network server or other
+     readily accessible means, then you must either (1) cause the
+     Corresponding Source to be so available, or (2) arrange to deprive
+     yourself of the benefit of the patent license for this particular
+     work, or (3) arrange, in a manner consistent with the requirements
+     of this License, to extend the patent license to downstream
+     recipients.  “Knowingly relying” means you have actual knowledge
+     that, but for the patent license, your conveying the covered work
+     in a country, or your recipient’s use of the covered work in a
+     country, would infringe one or more identifiable patents in that
+     country that you have reason to believe are valid.
+
+     If, pursuant to or in connection with a single transaction or
+     arrangement, you convey, or propagate by procuring conveyance of, a
+     covered work, and grant a patent license to some of the parties
+     receiving the covered work authorizing them to use, propagate,
+     modify or convey a specific copy of the covered work, then the
+     patent license you grant is automatically extended to all
+     recipients of the covered work and works based on it.
+
+     A patent license is “discriminatory” if it does not include within
+     the scope of its coverage, prohibits the exercise of, or is
+     conditioned on the non-exercise of one or more of the rights that
+     are specifically granted under this License.  You may not convey a
+     covered work if you are a party to an arrangement with a third
+     party that is in the business of distributing software, under which
+     you make payment to the third party based on the extent of your
+     activity of conveying the work, and under which the third party
+     grants, to any of the parties who would receive the covered work
+     from you, a discriminatory patent license (a) in connection with
+     copies of the covered work conveyed by you (or copies made from
+     those copies), or (b) primarily for and in connection with specific
+     products or compilations that contain the covered work, unless you
+     entered into that arrangement, or that patent license was granted,
+     prior to 28 March 2007.
+
+     Nothing in this License shall be construed as excluding or limiting
+     any implied license or other defenses to infringement that may
+     otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others’ Freedom.
+
+     If conditions are imposed on you (whether by court order, agreement
+     or otherwise) that contradict the conditions of this License, they
+     do not excuse you from the conditions of this License.  If you
+     cannot convey a covered work so as to satisfy simultaneously your
+     obligations under this License and any other pertinent obligations,
+     then as a consequence you may not convey it at all.  For example,
+     if you agree to terms that obligate you to collect a royalty for
+     further conveying from those to whom you convey the Program, the
+     only way you could satisfy both those terms and this License would
+     be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+     Notwithstanding any other provision of this License, you have
+     permission to link or combine any covered work with a work licensed
+     under version 3 of the GNU Affero General Public License into a
+     single combined work, and to convey the resulting work.  The terms
+     of this License will continue to apply to the part which is the
+     covered work, but the special requirements of the GNU Affero
+     General Public License, section 13, concerning interaction through
+     a network will apply to the combination as such.
+
+  14. Revised Versions of this License.
+
+     The Free Software Foundation may publish revised and/or new
+     versions of the GNU General Public License from time to time.  Such
+     new versions will be similar in spirit to the present version, but
+     may differ in detail to address new problems or concerns.
+
+     Each version is given a distinguishing version number.  If the
+     Program specifies that a certain numbered version of the GNU
+     General Public License “or any later version” applies to it, you
+     have the option of following the terms and conditions either of
+     that numbered version or of any later version published by the Free
+     Software Foundation.  If the Program does not specify a version
+     number of the GNU General Public License, you may choose any
+     version ever published by the Free Software Foundation.
+
+     If the Program specifies that a proxy can decide which future
+     versions of the GNU General Public License can be used, that
+     proxy’s public statement of acceptance of a version permanently
+     authorizes you to choose that version for the Program.
+
+     Later license versions may give you additional or different
+     permissions.  However, no additional obligations are imposed on any
+     author or copyright holder as a result of your choosing to follow a
+     later version.
+
+  15. Disclaimer of Warranty.
+
+     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+     APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+     COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS”
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE
+     RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
+     SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+     NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES
+     AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+     DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+     CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+     PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
+     THE POSSIBILITY OF SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+     If the disclaimer of warranty and limitation of liability provided
+     above cannot be given local legal effect according to their terms,
+     reviewing courts shall apply local law that most closely
+     approximates an absolute waiver of all civil liability in
+     connection with the Program, unless a warranty or assumption of
+     liability accompanies a copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+===========================
+
+How to Apply These Terms to Your New Programs
+=============================================
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+   To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least the
+“copyright” line and a pointer to where the full notice is found.
+
+     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
+     Copyright (C) YEAR NAME OF AUTHOR
+
+     This program is free software: you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation, either version 3 of the License, or (at
+     your option) any later version.
+
+     This program is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+   Also add information on how to contact you by electronic and paper
+mail.
+
+   If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+     PROGRAM Copyright (C) YEAR NAME OF AUTHOR
+     This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
+     This is free software, and you are welcome to redistribute it
+     under certain conditions; type ‘show c’ for details.
+
+   The hypothetical commands ‘show w’ and ‘show c’ should show the
+appropriate parts of the General Public License.  Of course, your
+program’s commands might be different; for a GUI interface, you would
+use an “about box”.
+
+   You should also get your employer (if you work as a programmer) or
+school, if any, to sign a “copyright disclaimer” for the program, if
+necessary.  For more information on this, and how to apply and follow
+the GNU GPL, see <https://www.gnu.org/licenses/>.
+
+   The GNU General Public License does not permit incorporating your
+program into proprietary programs.  If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library.  If this is what you want to do, use the
+GNU Lesser General Public License instead of this License.  But first,
+please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
+
+\1f
+File: dash.info,  Node: Index,  Prev: GPL,  Up: Top
+
+Index
+*****
+
+\0\b[index\0\b]
+* Menu:
+
+* !cdr:                                  Destructive operations.
+                                                              (line  16)
+* !cons:                                 Destructive operations.
+                                                              (line   8)
+* -->:                                   Threading macros.    (line  35)
+* ->:                                    Threading macros.    (line   9)
+* ->>:                                   Threading macros.    (line  22)
+* -all?:                                 Predicates.          (line  53)
+* -andfn:                                Function combinators.
+                                                              (line 184)
+* -annotate:                             Maps.                (line  86)
+* -any?:                                 Predicates.          (line  41)
+* -applify:                              Function combinators.
+                                                              (line  63)
+* -as->:                                 Threading macros.    (line  49)
+* -butlast:                              Other list operations.
+                                                              (line 405)
+* -clone:                                Tree operations.     (line 123)
+* -common-prefix:                        Reductions.          (line 242)
+* -common-suffix:                        Reductions.          (line 252)
+* -compose:                              Function combinators.
+                                                              (line  49)
+* -concat:                               List to list.        (line  23)
+* -cons*:                                Other list operations.
+                                                              (line  19)
+* -cons-pair?:                           Predicates.          (line 154)
+* -const:                                Function combinators.
+                                                              (line 128)
+* -contains?:                            Predicates.          (line 100)
+* -copy:                                 Maps.                (line 151)
+* -count:                                Reductions.          (line 172)
+* -cut:                                  Function combinators.
+                                                              (line 140)
+* -cycle:                                Unfolding.           (line  55)
+* -difference:                           Set operations.      (line  22)
+* -distinct:                             Set operations.      (line  73)
+* -dotimes:                              Side effects.        (line  80)
+* -doto:                                 Threading macros.    (line  99)
+* -drop:                                 Sublist selection.   (line 149)
+* -drop-last:                            Sublist selection.   (line 163)
+* -drop-while:                           Sublist selection.   (line 194)
+* -each:                                 Side effects.        (line   8)
+* -each-indexed:                         Side effects.        (line  38)
+* -each-r:                               Side effects.        (line  52)
+* -each-r-while:                         Side effects.        (line  65)
+* -each-while:                           Side effects.        (line  24)
+* -elem-index:                           Indexing.            (line   9)
+* -elem-indices:                         Indexing.            (line  23)
+* -every:                                Predicates.          (line  23)
+* -fifth-item:                           Other list operations.
+                                                              (line 380)
+* -filter:                               Sublist selection.   (line   8)
+* -find-index:                           Indexing.            (line  35)
+* -find-indices:                         Indexing.            (line  73)
+* -find-last-index:                      Indexing.            (line  54)
+* -first:                                Other list operations.
+                                                              (line 300)
+* -first-item:                           Other list operations.
+                                                              (line 328)
+* -fix:                                  Other list operations.
+                                                              (line 445)
+* -fixfn:                                Function combinators.
+                                                              (line 224)
+* -flatten:                              List to list.        (line  43)
+* -flatten-n:                            List to list.        (line  65)
+* -flip:                                 Function combinators.
+                                                              (line  95)
+* -fourth-item:                          Other list operations.
+                                                              (line 367)
+* -frequencies:                          Reductions.          (line 310)
+* -grade-down:                           Indexing.            (line 103)
+* -grade-up:                             Indexing.            (line  93)
+* -group-by:                             Partitioning.        (line 205)
+* -if-let:                               Binding.             (line  34)
+* -if-let*:                              Binding.             (line  45)
+* -inits:                                Reductions.          (line 222)
+* -insert-at:                            List to list.        (line 119)
+* -interleave:                           Other list operations.
+                                                              (line  56)
+* -interpose:                            Other list operations.
+                                                              (line  46)
+* -intersection:                         Set operations.      (line  36)
+* -iota:                                 Other list operations.
+                                                              (line  67)
+* -is-infix?:                            Predicates.          (line 140)
+* -is-prefix?:                           Predicates.          (line 116)
+* -is-suffix?:                           Predicates.          (line 128)
+* -iterate:                              Unfolding.           (line   9)
+* -iteratefn:                            Function combinators.
+                                                              (line 201)
+* -juxt:                                 Function combinators.
+                                                              (line  37)
+* -keep:                                 List to list.        (line   8)
+* -lambda:                               Binding.             (line 247)
+* -last:                                 Other list operations.
+                                                              (line 318)
+* -last-item:                            Other list operations.
+                                                              (line 393)
+* -let:                                  Binding.             (line  61)
+* -let*:                                 Binding.             (line 227)
+* -list:                                 Other list operations.
+                                                              (line 428)
+* -map:                                  Maps.                (line  10)
+* -map-first:                            Maps.                (line  38)
+* -map-indexed:                          Maps.                (line  68)
+* -map-last:                             Maps.                (line  53)
+* -map-when:                             Maps.                (line  22)
+* -mapcat:                               Maps.                (line 140)
+* -max:                                  Reductions.          (line 286)
+* -max-by:                               Reductions.          (line 296)
+* -min:                                  Reductions.          (line 262)
+* -min-by:                               Reductions.          (line 272)
+* -non-nil:                              Sublist selection.   (line  95)
+* -none?:                                Predicates.          (line  73)
+* -not:                                  Function combinators.
+                                                              (line 153)
+* -on:                                   Function combinators.
+                                                              (line  75)
+* -only-some?:                           Predicates.          (line  85)
+* -orfn:                                 Function combinators.
+                                                              (line 167)
+* -pad:                                  Other list operations.
+                                                              (line 241)
+* -partial:                              Function combinators.
+                                                              (line   8)
+* -partition:                            Partitioning.        (line  90)
+* -partition-after-item:                 Partitioning.        (line 195)
+* -partition-after-pred:                 Partitioning.        (line 162)
+* -partition-all:                        Partitioning.        (line 102)
+* -partition-all-in-steps:               Partitioning.        (line 126)
+* -partition-before-item:                Partitioning.        (line 185)
+* -partition-before-pred:                Partitioning.        (line 174)
+* -partition-by:                         Partitioning.        (line 138)
+* -partition-by-header:                  Partitioning.        (line 149)
+* -partition-in-steps:                   Partitioning.        (line 113)
+* -permutations:                         Set operations.      (line  60)
+* -powerset:                             Set operations.      (line  50)
+* -prodfn:                               Function combinators.
+                                                              (line 258)
+* -product:                              Reductions.          (line 201)
+* -reduce:                               Reductions.          (line  53)
+* -reduce-from:                          Reductions.          (line   8)
+* -reduce-r:                             Reductions.          (line  72)
+* -reduce-r-from:                        Reductions.          (line  26)
+* -reductions:                           Reductions.          (line 136)
+* -reductions-from:                      Reductions.          (line 100)
+* -reductions-r:                         Reductions.          (line 154)
+* -reductions-r-from:                    Reductions.          (line 118)
+* -remove:                               Sublist selection.   (line  26)
+* -remove-at:                            List to list.        (line 156)
+* -remove-at-indices:                    List to list.        (line 175)
+* -remove-first:                         Sublist selection.   (line  44)
+* -remove-item:                          Sublist selection.   (line  84)
+* -remove-last:                          Sublist selection.   (line  65)
+* -repeat:                               Unfolding.           (line  44)
+* -replace:                              List to list.        (line  77)
+* -replace-at:                           List to list.        (line 130)
+* -replace-first:                        List to list.        (line  91)
+* -replace-last:                         List to list.        (line 105)
+* -rotate:                               Other list operations.
+                                                              (line   8)
+* -rotate-args:                          Function combinators.
+                                                              (line 112)
+* -rpartial:                             Function combinators.
+                                                              (line  22)
+* -running-product:                      Reductions.          (line 211)
+* -running-sum:                          Reductions.          (line 190)
+* -same-items?:                          Set operations.      (line  88)
+* -second-item:                          Other list operations.
+                                                              (line 341)
+* -select-by-indices:                    Sublist selection.   (line 211)
+* -select-column:                        Sublist selection.   (line 241)
+* -select-columns:                       Sublist selection.   (line 222)
+* -separate:                             Partitioning.        (line  75)
+* -setq:                                 Binding.             (line 270)
+* -slice:                                Sublist selection.   (line 105)
+* -snoc:                                 Other list operations.
+                                                              (line  32)
+* -some:                                 Predicates.          (line   8)
+* -some-->:                              Threading macros.    (line  86)
+* -some->:                               Threading macros.    (line  62)
+* -some->>:                              Threading macros.    (line  74)
+* -sort:                                 Other list operations.
+                                                              (line 415)
+* -splice:                               Maps.                (line 102)
+* -splice-list:                          Maps.                (line 127)
+* -split-at:                             Partitioning.        (line   8)
+* -split-on:                             Partitioning.        (line  40)
+* -split-when:                           Partitioning.        (line  58)
+* -split-with:                           Partitioning.        (line  23)
+* -sum:                                  Reductions.          (line 180)
+* -table:                                Other list operations.
+                                                              (line 256)
+* -table-flat:                           Other list operations.
+                                                              (line 275)
+* -tails:                                Reductions.          (line 232)
+* -take:                                 Sublist selection.   (line 121)
+* -take-last:                            Sublist selection.   (line 135)
+* -take-while:                           Sublist selection.   (line 177)
+* -third-item:                           Other list operations.
+                                                              (line 354)
+* -tree-map:                             Tree operations.     (line  28)
+* -tree-map-nodes:                       Tree operations.     (line  39)
+* -tree-mapreduce:                       Tree operations.     (line  85)
+* -tree-mapreduce-from:                  Tree operations.     (line 104)
+* -tree-reduce:                          Tree operations.     (line  53)
+* -tree-reduce-from:                     Tree operations.     (line  70)
+* -tree-seq:                             Tree operations.     (line   8)
+* -unfold:                               Unfolding.           (line  25)
+* -union:                                Set operations.      (line   8)
+* -unzip:                                Other list operations.
+                                                              (line 215)
+* -unzip-lists:                          Other list operations.
+                                                              (line 196)
+* -update-at:                            List to list.        (line 142)
+* -when-let:                             Binding.             (line   9)
+* -when-let*:                            Binding.             (line  21)
+* -zip:                                  Other list operations.
+                                                              (line 150)
+* -zip-fill:                             Other list operations.
+                                                              (line 176)
+* -zip-lists:                            Other list operations.
+                                                              (line 114)
+* -zip-lists-fill:                       Other list operations.
+                                                              (line 135)
+* -zip-pair:                             Other list operations.
+                                                              (line  98)
+* -zip-with:                             Other list operations.
+                                                              (line  80)
+* dash-fontify-mode:                     Fontification of special variables.
+                                                              (line   6)
+* dash-register-info-lookup:             Info symbol lookup.  (line   6)
+* global-dash-fontify-mode:              Fontification of special variables.
+                                                              (line  12)
+
+
+\1f
+Tag Table:
+Node: Top\7f742
+Node: Installation\7f2397
+Node: Using in a package\7f3159
+Node: Fontification of special variables\7f3504
+Node: Info symbol lookup\7f4294
+Node: Functions\7f4877
+Node: Maps\7f6361
+Ref: -map\7f6658
+Ref: -map-when\7f7031
+Ref: -map-first\7f7605
+Ref: -map-last\7f8200
+Ref: -map-indexed\7f8790
+Ref: -annotate\7f9476
+Ref: -splice\7f10080
+Ref: -splice-list\7f11155
+Ref: -mapcat\7f11614
+Ref: -copy\7f11987
+Node: Sublist selection\7f12253
+Ref: -filter\7f12446
+Ref: -remove\7f12999
+Ref: -remove-first\7f13548
+Ref: -remove-last\7f14396
+Ref: -remove-item\7f15126
+Ref: -non-nil\7f15526
+Ref: -slice\7f15808
+Ref: -take\7f16337
+Ref: -take-last\7f16755
+Ref: -drop\7f17192
+Ref: -drop-last\7f17639
+Ref: -take-while\7f18071
+Ref: -drop-while\7f18698
+Ref: -select-by-indices\7f19331
+Ref: -select-columns\7f19842
+Ref: -select-column\7f20545
+Node: List to list\7f21008
+Ref: -keep\7f21200
+Ref: -concat\7f21776
+Ref: -flatten\7f22556
+Ref: -flatten-n\7f23318
+Ref: -replace\7f23702
+Ref: -replace-first\7f24163
+Ref: -replace-last\7f24658
+Ref: -insert-at\7f25146
+Ref: -replace-at\7f25471
+Ref: -update-at\7f25858
+Ref: -remove-at\7f26399
+Ref: -remove-at-indices\7f27026
+Node: Reductions\7f27716
+Ref: -reduce-from\7f27912
+Ref: -reduce-r-from\7f28636
+Ref: -reduce\7f29899
+Ref: -reduce-r\7f30650
+Ref: -reductions-from\7f31928
+Ref: -reductions-r-from\7f32734
+Ref: -reductions\7f33564
+Ref: -reductions-r\7f34275
+Ref: -count\7f35020
+Ref: -sum\7f35250
+Ref: -running-sum\7f35438
+Ref: -product\7f35759
+Ref: -running-product\7f35967
+Ref: -inits\7f36308
+Ref: -tails\7f36553
+Ref: -common-prefix\7f36798
+Ref: -common-suffix\7f37092
+Ref: -min\7f37386
+Ref: -min-by\7f37612
+Ref: -max\7f38133
+Ref: -max-by\7f38358
+Ref: -frequencies\7f38884
+Node: Unfolding\7f39499
+Ref: -iterate\7f39740
+Ref: -unfold\7f40187
+Ref: -repeat\7f40992
+Ref: -cycle\7f41276
+Node: Predicates\7f41673
+Ref: -some\7f41850
+Ref: -every\7f42279
+Ref: -any?\7f42993
+Ref: -all?\7f43342
+Ref: -none?\7f44084
+Ref: -only-some?\7f44404
+Ref: -contains?\7f44949
+Ref: -is-prefix?\7f45455
+Ref: -is-suffix?\7f45787
+Ref: -is-infix?\7f46119
+Ref: -cons-pair?\7f46479
+Node: Partitioning\7f46810
+Ref: -split-at\7f46998
+Ref: -split-with\7f47662
+Ref: -split-on\7f48302
+Ref: -split-when\7f48973
+Ref: -separate\7f49616
+Ref: -partition\7f50150
+Ref: -partition-all\7f50599
+Ref: -partition-in-steps\7f51024
+Ref: -partition-all-in-steps\7f51570
+Ref: -partition-by\7f52084
+Ref: -partition-by-header\7f52462
+Ref: -partition-after-pred\7f53063
+Ref: -partition-before-pred\7f53516
+Ref: -partition-before-item\7f53901
+Ref: -partition-after-item\7f54208
+Ref: -group-by\7f54510
+Node: Indexing\7f54943
+Ref: -elem-index\7f55145
+Ref: -elem-indices\7f55632
+Ref: -find-index\7f56091
+Ref: -find-last-index\7f56760
+Ref: -find-indices\7f57411
+Ref: -grade-up\7f58173
+Ref: -grade-down\7f58580
+Node: Set operations\7f58994
+Ref: -union\7f59177
+Ref: -difference\7f59607
+Ref: -intersection\7f60035
+Ref: -powerset\7f60464
+Ref: -permutations\7f60741
+Ref: -distinct\7f61179
+Ref: -same-items?\7f61573
+Node: Other list operations\7f62182
+Ref: -rotate\7f62407
+Ref: -cons*\7f62760
+Ref: -snoc\7f63182
+Ref: -interpose\7f63594
+Ref: -interleave\7f63888
+Ref: -iota\7f64254
+Ref: -zip-with\7f64737
+Ref: -zip-pair\7f65545
+Ref: -zip-lists\7f66111
+Ref: -zip-lists-fill\7f66909
+Ref: -zip\7f67619
+Ref: -zip-fill\7f68646
+Ref: -unzip-lists\7f69560
+Ref: -unzip\7f70183
+Ref: -pad\7f71176
+Ref: -table\7f71661
+Ref: -table-flat\7f72447
+Ref: -first\7f73452
+Ref: -last\7f73985
+Ref: -first-item\7f74331
+Ref: -second-item\7f74743
+Ref: -third-item\7f75160
+Ref: -fourth-item\7f75535
+Ref: -fifth-item\7f75913
+Ref: -last-item\7f76288
+Ref: -butlast\7f76649
+Ref: -sort\7f76894
+Ref: -list\7f77388
+Ref: -fix\7f77957
+Node: Tree operations\7f78446
+Ref: -tree-seq\7f78642
+Ref: -tree-map\7f79503
+Ref: -tree-map-nodes\7f79943
+Ref: -tree-reduce\7f80807
+Ref: -tree-reduce-from\7f81689
+Ref: -tree-mapreduce\7f82289
+Ref: -tree-mapreduce-from\7f83148
+Ref: -clone\7f84433
+Node: Threading macros\7f84771
+Ref: ->\7f84996
+Ref: ->>\7f85484
+Ref: -->\7f85987
+Ref: -as->\7f86544
+Ref: -some->\7f86998
+Ref: -some->>\7f87383
+Ref: -some-->\7f87830
+Ref: -doto\7f88397
+Node: Binding\7f88950
+Ref: -when-let\7f89157
+Ref: -when-let*\7f89618
+Ref: -if-let\7f90147
+Ref: -if-let*\7f90513
+Ref: -let\7f91136
+Ref: -let*\7f97226
+Ref: -lambda\7f98163
+Ref: -setq\7f98969
+Node: Side effects\7f99770
+Ref: -each\7f99964
+Ref: -each-while\7f100491
+Ref: -each-indexed\7f101111
+Ref: -each-r\7f101703
+Ref: -each-r-while\7f102145
+Ref: -dotimes\7f102789
+Node: Destructive operations\7f103342
+Ref: !cons\7f103560
+Ref: !cdr\7f103764
+Node: Function combinators\7f103957
+Ref: -partial\7f104161
+Ref: -rpartial\7f104679
+Ref: -juxt\7f105327
+Ref: -compose\7f105779
+Ref: -applify\7f106386
+Ref: -on\7f106816
+Ref: -flip\7f107588
+Ref: -rotate-args\7f108112
+Ref: -const\7f108741
+Ref: -cut\7f109083
+Ref: -not\7f109563
+Ref: -orfn\7f110107
+Ref: -andfn\7f110900
+Ref: -iteratefn\7f111687
+Ref: -fixfn\7f112389
+Ref: -prodfn\7f113963
+Node: Development\7f115114
+Node: Contribute\7f115403
+Node: Contributors\7f116415
+Node: FDL\7f118508
+Node: GPL\7f143828
+Node: Index\7f181577
+\1f
+End Tag Table
+
+\1f
+Local Variables:
+coding: utf-8
+End:
diff --git a/elpa/dash-20250312.1307/dir b/elpa/dash-20250312.1307/dir
new file mode 100644 (file)
index 0000000..7d473f4
--- /dev/null
@@ -0,0 +1,18 @@
+This is the file .../info/dir, which contains the
+topmost node of the Info hierarchy, called (dir)Top.
+The first time you invoke Info you start off looking at this node.
+\1f
+File: dir,     Node: Top       This is the top of the INFO tree
+
+  This (the Directory node) gives a menu of major topics.
+  Typing "q" exits, "H" lists all Info commands, "d" returns here,
+  "h" gives a primer for first-timers,
+  "mEmacs<Return>" visits the Emacs manual, etc.
+
+  In Emacs, you can click mouse button 2 on a menu item or cross reference
+  to select it.
+
+* Menu:
+
+Emacs
+* Dash: (dash.info).            A modern list library for GNU Emacs.