diff options
Diffstat (limited to 'elpa/dash-20210826.1149')
-rw-r--r-- | elpa/dash-20210826.1149/dash-autoloads.el | 74 | ||||
-rw-r--r-- | elpa/dash-20210826.1149/dash-pkg.el | 12 | ||||
-rw-r--r-- | elpa/dash-20210826.1149/dash.el | 3531 | ||||
-rw-r--r-- | elpa/dash-20210826.1149/dash.elc | bin | 138391 -> 0 bytes | |||
-rw-r--r-- | elpa/dash-20210826.1149/dash.info | 4738 | ||||
-rw-r--r-- | elpa/dash-20210826.1149/dir | 18 |
6 files changed, 0 insertions, 8373 deletions
diff --git a/elpa/dash-20210826.1149/dash-autoloads.el b/elpa/dash-20210826.1149/dash-autoloads.el deleted file mode 100644 index 3a96693..0000000 --- a/elpa/dash-20210826.1149/dash-autoloads.el +++ /dev/null @@ -1,74 +0,0 @@ -;;; dash-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "dash" "dash.el" (0 0 0 0)) -;;; Generated autoloads from dash.el - -(autoload 'dash-fontify-mode "dash" "\ -Toggle fontification of Dash special variables. - -If called interactively, enable Dash-Fontify mode if ARG is -positive, and disable it if ARG is zero or negative. If called -from Lisp, also enable the mode if ARG is omitted or nil, and -toggle it if ARG is `toggle'; disable the mode otherwise. - -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'. - -\(fn &optional ARG)" t nil) - -(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, enable the mode if -ARG is omitted or nil. - -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 nil) - -(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 nil) - -(if (fboundp 'register-definition-prefixes) (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-"))) - -;;;*** - -;;;### (autoloads nil nil ("dash-pkg.el") (0 0 0 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; dash-autoloads.el ends here diff --git a/elpa/dash-20210826.1149/dash-pkg.el b/elpa/dash-20210826.1149/dash-pkg.el deleted file mode 100644 index 7dc2d7a..0000000 --- a/elpa/dash-20210826.1149/dash-pkg.el +++ /dev/null @@ -1,12 +0,0 @@ -(define-package "dash" "20210826.1149" "A modern list library for Emacs" - '((emacs "24")) - :commit "da167c51e9fd167a48d06c7c0ee8e3ac7abd9718" :authors - '(("Magnar Sveen" . "magnars@gmail.com")) - :maintainer - '("Magnar Sveen" . "magnars@gmail.com") - :keywords - '("extensions" "lisp") - :url "https://github.com/magnars/dash.el") -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/dash-20210826.1149/dash.el b/elpa/dash-20210826.1149/dash.el deleted file mode 100644 index 6386c5f..0000000 --- a/elpa/dash-20210826.1149/dash.el +++ /dev/null @@ -1,3531 +0,0 @@ -;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*- - -;; Copyright (C) 2012-2021 Free Software Foundation, Inc. - -;; Author: Magnar Sveen <magnars@gmail.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: - -;; TODO: `gv' was introduced in Emacs 24.3, so remove this and all -;; calls to `defsetf' when support for earlier versions is dropped. -(eval-when-compile - (unless (fboundp 'gv-define-setter) - (require 'cl))) - -(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) - it it-index) - (ignore it it-index) - (while ,l - (setq it (pop ,l) it-index ,i ,i (1+ ,i)) - ,@body)))) - -(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 it it-index) - (ignore it it-index) - (while (and ,l (setq ,elt (pop ,l) it ,elt it-index ,i) ,pred) - (setq it ,elt it-index ,i ,i (1+ ,i)) - ,@body)))) - -(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'." - (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'." - (--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'." - (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'." - (--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'." - (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'." - (--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)) - (let (acc it) - (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'." - (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'." - (--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'." - (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'." - (--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'." - (--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'." - (--remove-first (funcall pred it) list)) - -(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'." - (--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'." - (--keep (funcall fn it) list)) - -(defun -non-nil (list) - "Return a copy of LIST with all nil items removed." - (declare (pure t) (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'." - (--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) - "Return a new list where the elements in LIST that do not match the PRED function -are unchanged, and where the elements in LIST that do match the PRED function are mapped -through the REP function. - -Alias: `-replace-where' - -See also: `-update-at'" - (--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) - "Replace first item in LIST satisfying PRED with result of REP called on this item. - -See also: `-map-when', `-replace-first'" - (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) ,pred) (lambda (it) (ignore it) ,rep) ,list)) - -(defun -map-last (pred rep list) - "Replace last item in LIST satisfying PRED with result of REP called on this item. - -See also: `-map-when', `-replace-last'" - (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) ,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." - (--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." - (--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) - -(defun -concat (&rest lists) - "Return a new list with the concatenation of the elements in the supplied LISTS." - (declare (pure t) (side-effect-free t)) - (apply 'append lists)) - -(defalias '-copy 'copy-sequence - "Create a shallow copy of LIST. - -\(fn LIST)") - -(defun -splice (pred fun list) - "Splice lists generated by FUN in place of elements matching PRED in LIST. - -FUN takes the element matching PRED as input. - -This function can be used as replacement for `,@' in case you -need to splice several lists at marked positions (for example -with keywords). - -See also: `-splice-list', `-insert-at'" - (let (r) - (--each list - (if (funcall pred it) - (let ((new (funcall fun it))) - (--each new (!cons it r))) - (!cons it r))) - (nreverse r))) - -(defmacro --splice (pred form list) - "Anaphoric form of `-splice'." - (declare (debug (def-form def-form form))) - `(-splice (lambda (it) ,pred) (lambda (it) ,form) ,list)) - -(defun -splice-list (pred new-list list) - "Splice NEW-LIST in place of elements matching PRED in LIST. - -See also: `-splice', `-insert-at'" - (-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) ,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 (pure t) (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 ELEMENTS is non nil, append these to the list as well." - (-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 `car'. - -Alias: `-find'. - -This function's anaphoric counterpart is `--first'." - (--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'." - (--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'." - (--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." - (--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'. - -\(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) - -(defalias '-second-item 'cadr - "Return the second item of LIST, or nil if LIST is too short. - -See also: `-third-item'. - -\(fn LIST)") - -(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: `-fourth-item'. - -\(fn LIST)") - -(defun -fourth-item (list) - "Return the fourth item of LIST, or nil if LIST is too short. - -See also: `-fifth-item'." - (declare (pure t) (side-effect-free t)) - (car (cdr (cdr (cdr list))))) - -(defun -fifth-item (list) - "Return the fifth item of LIST, or nil if LIST is too short. - -See also: `-last-item'." - (declare (pure t) (side-effect-free t)) - (car (cdr (cdr (cdr (cdr list)))))) - -(defun -last-item (list) - "Return the last item of LIST, or nil on an empty list." - (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." - (--count (funcall pred it) list)) - -(defun ---truthy? (obj) - "Return OBJ as a boolean value (t or nil)." - (declare (pure t) (side-effect-free t)) - (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'" - (--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?'." - (--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'" - (--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 at least one item of LIST matches PRED and at least one item of LIST does not match PRED. -Return `nil` both if all items match the predicate or if none of the items match the predicate. - -Alias: `-only-some-p'" - (--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 (pure t) (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'." - (--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'." - (--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 (pure t) (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 (pure t) (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 (pure t) (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 (pure t) (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) - "Return a list with element at Nth position in LIST replaced with `(func (nth n list))`. - -See also: `-map-when'" - (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) ,form) ,list)) - -(defun -remove-at (n list) - "Return a list with element at Nth position in LIST removed. - -See also: `-remove-at-indices', `-remove'" - (declare (pure t) (side-effect-free t)) - (-remove-at-indices (list n) list)) - -(defun -remove-at-indices (indices list) - "Return a list whose elements are elements from LIST without -elements selected as `(nth i list)` for all i -from INDICES. - -See also: `-remove-at', `-remove'" - (declare (pure t) (side-effect-free t)) - (let* ((indices (-sort '< indices)) - (diffs (cons (car indices) (-map '1- (-zip-with '- (cdr indices) indices)))) - r) - (--each diffs - (let ((split (-split-at it list))) - (!cons (car split) r) - (setq list (cdr (cadr split))))) - (!cons list r) - (apply '-concat (nreverse r)))) - -(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) - "Return a list of ((-take-while PRED LIST) (-drop-while PRED LIST)), in no more than one pass through the list." - (--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) ,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'." - (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) - "Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one pass through the list." - (--separate (funcall pred it) list)) - -(defun dash--partition-all-in-steps-reversed (n step list) - "Used by `-partition-all-in-steps' and `-partition-in-steps'." - (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) - "Return a new list with the items in LIST grouped into N-sized sublists at offsets STEP apart. -The last 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) - "Return a new list with the items in LIST grouped into N-sized sublists at offsets STEP apart. -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)) - (!cdr 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." - (--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)." - (--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'." - (--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." - (nreverse (-map #'reverse - (-partition-after-pred pred (reverse list))))) - -(defun -partition-after-item (item list) - "Partition directly after each time ITEM appears in LIST." - (-partition-after-pred (lambda (ele) (equal ele item)) - list)) - -(defun -partition-before-item (item list) - "Partition directly before each time ITEM appears in LIST." - (-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'." - (--group-by (funcall fn it) list)) - -(defun -interpose (sep list) - "Return a new list of all elements in LIST separated by SEP." - (declare (pure t) (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 (pure t) (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) - "Anaphoric form of `-zip-with'. - -The elements in list1 are bound as symbol `it', the elements in list2 as symbol `other'." - (declare (debug (form form form))) - (let ((r (make-symbol "result")) - (l1 (make-symbol "list1")) - (l2 (make-symbol "list2"))) - `(let ((,r nil) - (,l1 ,list1) - (,l2 ,list2)) - (while (and ,l1 ,l2) - (let ((it (car ,l1)) - (other (car ,l2))) - (!cons ,form ,r) - (!cdr ,l1) - (!cdr ,l2))) - (nreverse ,r)))) - -(defun -zip-with (fn list1 list2) - "Zip the two lists LIST1 and LIST2 using a function FN. This -function is applied pairwise taking as first argument element of -LIST1 and as second argument element of LIST2 at corresponding -position. - -The anaphoric form `--zip-with' binds the elements from LIST1 as symbol `it', -and the elements from LIST2 as symbol `other'." - (--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 elements of each list, and so on. The lengths of the returned -groupings are equal to the length of the shortest input list. - -The return value is always list of lists, which is a difference -from `-zip-pair' which returns a cons-cell in case two input -lists are provided. - -See also: `-zip'" - (declare (pure t) (side-effect-free t)) - (when lists - (let (results) - (while (-none? 'null lists) - (setq results (cons (mapcar 'car lists) results)) - (setq lists (mapcar 'cdr lists))) - (nreverse results)))) - -(defun -zip (&rest lists) - "Zip LISTS together. Group the head of each list, followed by the -second elements of each list, and so on. The lengths of the returned -groupings are equal to the length of the shortest input list. - -If two lists are provided as arguments, return the groupings as a list -of cons cells. Otherwise, return the groupings as a list of lists. - -Use `-zip-lists' if you need the return value to always be a list -of lists. - -Alias: `-zip-pair' - -See also: `-zip-lists'" - (declare (pure t) (side-effect-free t)) - (when lists - (let (results) - (while (-none? 'null lists) - (setq results (cons (mapcar 'car lists) results)) - (setq lists (mapcar 'cdr lists))) - (setq results (nreverse results)) - (if (= (length lists) 2) - ;; to support backward compatibility, return - ;; a cons cell if two lists were provided - (--map (cons (car it) (cadr it)) results) - results)))) - -(defalias '-zip-pair '-zip) - -(defun -zip-fill (fill-value &rest lists) - "Zip LISTS, with FILL-VALUE padded onto the shorter lists. The -lengths of the returned groupings are equal to the length of the -longest input list." - (declare (pure t) (side-effect-free t)) - (apply '-zip (apply '-pad (cons fill-value lists)))) - -(defun -unzip (lists) - "Unzip LISTS. - -This works just like `-zip' 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 the same length). - -Note in particular that calling this on a list of two lists will -return a list of cons-cells such that the above identity works. - -See also: `-zip'" - (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) - "Appends FILL-VALUE to the end of each list in LISTS such that they -will all have the same length." - (let* ((annotations (-annotate 'length lists)) - (n (-max (-map 'car annotations)))) - (--map (append (cdr it) (-repeat (- n (car it)) fill-value)) annotations))) - -(defun -annotate (fn list) - "Return a list of cons cells where each cell is FN applied to each -element of LIST paired with the unmodified element of LIST." - (-zip (-map fn list) list)) - -(defmacro --annotate (form list) - "Anaphoric version of `-annotate'." - (declare (debug (def-form form))) - `(-annotate (lambda (it) ,form) ,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'" - (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'" - (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))) - -(defun -elem-index (elem list) - "Return the index of the first element in the given LIST which -is equal to the query element ELEM, or nil if there is no -such element." - (declare (pure t) (side-effect-free t)) - (car (-elem-indices elem list))) - -(defun -elem-indices (elem list) - "Return the indices of all elements in LIST equal to the query -element ELEM, in ascending order." - (declare (pure t) (side-effect-free t)) - (-find-indices (-partial 'equal elem) list)) - -(defun -find-indices (pred list) - "Return the indices of all elements in LIST satisfying the -predicate PRED, in ascending order." - (apply 'append (--map-indexed (when (funcall pred it) (list it-index)) list))) - -(defmacro --find-indices (form list) - "Anaphoric version of `-find-indices'." - (declare (debug (def-form form))) - `(-find-indices (lambda (it) ,form) ,list)) - -(defun -find-index (pred list) - "Take a predicate PRED and a LIST and return the index of the -first element in the list satisfying the predicate, or nil if -there is no such element. - -See also `-first'." - (car (-find-indices pred list))) - -(defmacro --find-index (form list) - "Anaphoric version of `-find-index'." - (declare (debug (def-form form))) - `(-find-index (lambda (it) ,form) ,list)) - -(defun -find-last-index (pred list) - "Take a predicate PRED and a LIST and return the index of the -last element in the list satisfying the predicate, or nil if -there is no such element. - -See also `-last'." - (-last-item (-find-indices pred list))) - -(defmacro --find-last-index (form list) - "Anaphoric version of `-find-last-index'." - (declare (debug (def-form form))) - `(-find-last-index (lambda (it) ,form) ,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 in 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." - (->> (--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." - (->> (--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 (apply '-zip (-pad 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 - ((symbolp 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 (--map (list (caar it) (cadr it)) (-zip 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))) - -(defvar -compare-fn nil - "Tests for equality use this function or `equal' if this is nil. -It should only be set using dynamic scope with a let, like: - - (let ((-compare-fn #\\='=)) (-union numbers1 numbers2 numbers3)") - -(defun -distinct (list) - "Return a new list with all duplicates removed. -The test for equality is done with `equal', -or with `-compare-fn' if that's non-nil. - -Alias: `-uniq'" - ;; Implementation note: The speedup gained from hash table lookup - ;; starts to outweigh its overhead for lists of length greater than - ;; 32. See discussion in PR #305. - (let* ((len (length list)) - (lut (and (> len 32) - ;; Check that `-compare-fn' is a valid hash-table - ;; lookup function or `nil'. - (memq -compare-fn '(nil equal eq eql)) - (make-hash-table :test (or -compare-fn #'equal) - :size len)))) - (if lut - (--filter (unless (gethash it lut) - (puthash it t lut)) - list) - (--each list (unless (-contains? lut it) (!cons it lut))) - (nreverse lut)))) - -(defalias '-uniq '-distinct) - -(defun -union (list list2) - "Return a new list containing the elements of LIST and elements of LIST2 that are not in LIST. -The test for equality is done with `equal', -or with `-compare-fn' if that's non-nil." - ;; We fall back to iteration implementation if the comparison - ;; function isn't one of `eq', `eql' or `equal'. - (let* ((result (reverse list)) - ;; TODO: get rid of this dynamic variable, pass it as an - ;; argument instead. - (-compare-fn (if (bound-and-true-p -compare-fn) - -compare-fn - 'equal))) - (if (memq -compare-fn '(eq eql equal)) - (let ((ht (make-hash-table :test -compare-fn))) - (--each list (puthash it t ht)) - (--each list2 (unless (gethash it ht) (!cons it result)))) - (--each list2 (unless (-contains? result it) (!cons it result)))) - (nreverse result))) - -(defun -intersection (list list2) - "Return a new list containing only the elements that are members of both LIST and LIST2. -The test for equality is done with `equal', -or with `-compare-fn' if that's non-nil." - (--filter (-contains? list2 it) list)) - -(defun -difference (list list2) - "Return a new list with only the members of LIST that are not in LIST2. -The test for equality is done with `equal', -or with `-compare-fn' if that's non-nil." - (--filter (not (-contains? list2 it)) list)) - -(defun -powerset (list) - "Return the power set of LIST." - (if (null list) '(()) - (let ((last (-powerset (cdr list)))) - (append (mapcar (lambda (x) (cons (car list) x)) last) - last)))) - -(defun -permutations (list) - "Return the permutations of LIST." - (if (null list) '(()) - (apply #'append - (mapcar (lambda (x) - (mapcar (lambda (perm) (cons x perm)) - (-permutations (remove x list)))) - list)))) - -(defun -inits (list) - "Return all prefixes of LIST." - (let ((res (list list))) - (setq list (reverse list)) - (while list - (push (reverse (!cdr list)) res)) - res)) - -(defun -tails (list) - "Return all suffixes of LIST" - (-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." - (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's non-nil. - -Alias: `-contains-p'" - (not - (null - (cond - ((null -compare-fn) (member element list)) - ((eq -compare-fn 'eq) (memq element list)) - ((eq -compare-fn 'eql) (memql element list)) - (t - (let ((lst list)) - (while (and lst - (not (funcall -compare-fn element (car lst)))) - (setq lst (cdr lst))) - lst)))))) - -(defalias '-contains-p '-contains?) - -(defun -same-items? (list list2) - "Return true if LIST and LIST2 has the same items. - -The order of the elements in the lists does not matter. - -Alias: `-same-items-p'" - (let ((length-a (length list)) - (length-b (length list2))) - (and - (= length-a length-b) - (= length-a (length (-intersection list 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." - (sort (copy-sequence list) comparator)) - -(defmacro --sort (form list) - "Anaphoric form of `-sort'." - (declare (debug (def-form form))) - `(-sort (lambda (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 t)) - (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 (pure t) (side-effect-free t)) - (and (natnump n) (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." - (--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." - (--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) ,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) ,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 (pure t) (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'." - (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) ,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." - (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) ,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 t)) - (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)) - (cond - ((-cons-pair? val) (-cons-to-list val)) - (t (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." - (cond - ((not tree) nil) - ((-cons-pair? tree) (funcall fn tree)) - ((listp tree) - (-reduce-r-from folder init-value (mapcar (lambda (x) (-tree-mapreduce-from fn folder init-value x)) tree))) - (t (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) ,form) (lambda (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." - (cond - ((not tree) nil) - ((-cons-pair? tree) (funcall fn tree)) - ((listp tree) - (-reduce-r folder (mapcar (lambda (x) (-tree-mapreduce fn folder x)) tree))) - (t (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) ,form) (lambda (it acc) ,folder) ,tree)) - -(defun -tree-map (fn tree) - "Apply FN to each element of TREE while preserving the tree structure." - (cond - ((not tree) nil) - ((-cons-pair? tree) (funcall fn tree)) - ((listp tree) - (mapcar (lambda (x) (-tree-map fn x)) tree)) - (t (funcall fn tree)))) - -(defmacro --tree-map (form tree) - "Anaphoric form of `-tree-map'." - (declare (debug (def-form form))) - `(-tree-map (lambda (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." - (cond - ((not tree) nil) - ((-cons-pair? tree) tree) - ((listp tree) - (-reduce-r-from fn init-value (mapcar (lambda (x) (-tree-reduce-from fn init-value x)) tree))) - (t 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) ,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." - (cond - ((not tree) nil) - ((-cons-pair? tree) tree) - ((listp tree) - (-reduce-r fn (mapcar (lambda (x) (-tree-reduce fn x)) tree))) - (t tree))) - -(defmacro --tree-reduce (form tree) - "Anaphoric form of `-tree-reduce'." - (declare (debug (def-form form))) - `(-tree-reduce (lambda (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." - (if (funcall pred tree) - (funcall fun tree) - (if (and (listp tree) - (not (-cons-pair? 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) ,pred) (lambda (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." - (cons tree - (when (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) ,branch) (lambda (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 (pure t) (side-effect-free t)) - (-tree-map 'identity list)) - -;;; 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 t)) - (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 t)) - (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 t)) - (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 t)) - (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 t)) - (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 t)) - (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 t)) - (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 t)) - (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 t)) - ;; 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 t)) - ;; 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)))." - (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." - (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." - (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) - "Take a list of n functions and return a function that takes a -list of length n, applying i-th function to i-th 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))" - (lambda (x) (-zip-with 'funcall fns x))) - -;;; 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?" - "--annotate" - "--any?" - "--count" - "--dotimes" - "--doto" - "--drop-while" - "--each" - "--each-r" - "--each-r-while" - "--each-while" - "--filter" - "--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?" - "--only-some?" - "--partition-by" - "--partition-by-header" - "--reduce" - "--reduce-from" - "--reduce-r" - "--reduce-r-from" - "--reductions" - "--reductions-from" - "--reductions-r" - "--reductions-r-from" - "--remove" - "--remove-first" - "--remove-last" - "--separate" - "--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->" - "-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") - :group 'dash - :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'." - :group 'dash :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 - :group 'dash) - -(defcustom dash-enable-fontlock nil - "If non-nil, fontify Dash macro calls and special variables." - :group 'dash - :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") - -;;; 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-20210826.1149/dash.elc b/elpa/dash-20210826.1149/dash.elc Binary files differdeleted file mode 100644 index c37e49e..0000000 --- a/elpa/dash-20210826.1149/dash.elc +++ /dev/null diff --git a/elpa/dash-20210826.1149/dash.info b/elpa/dash-20210826.1149/dash.info deleted file mode 100644 index a6a2dc6..0000000 --- a/elpa/dash-20210826.1149/dash.info +++ /dev/null @@ -1,4738 +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–2021 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 - - -File: dash.info, Node: Top, Next: Installation, Up: (dir) - -Dash -**** - -This manual is for Dash version 2.19.1. - - Copyright © 2012–2021 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. - - -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. - - -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")) - - -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) - - -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)) - - -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:: - - -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) - Return a new list where the elements in LIST that do not match the - PRED function are unchanged, and where the elements in LIST that do - match the PRED function 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) - Replace first item in LIST satisfying PRED with result of REP - called on this 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) - Replace last item in LIST satisfying PRED with result of REP called - on this 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) - Return a list of cons cells where each cell is FN applied to each - element of LIST paired with the unmodified element of LIST. - - (-annotate '1+ '(1 2 3)) - ⇒ ((2 . 1) (3 . 2) (4 . 3)) - (-annotate 'length '(("h" "e" "l" "l" "o") ("hello" "world"))) - ⇒ ((5 "h" "e" "l" "l" "o") (2 "hello" "world")) - (--annotate (< 1 it) '(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 elements matching PRED in - LIST. - - FUN takes the element matching PRED as input. - - This function can be used as replacement for ‘,@’ in case you need - to splice several lists at marked positions (for example with - keywords). - - See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’ - (*note -insert-at::) - - (-splice 'even? (lambda (x) (list x x)) '(1 2 3 4)) - ⇒ (1 2 2 3 4 4) - (--splice 't (list it it) '(1 2 3 4)) - ⇒ (1 1 2 2 3 3 4 4) - (--splice (equal it :magic) '((list of) (magical) (code)) '((foo) (bar) :magic (baz))) - ⇒ ((foo) (bar) (list of) (magical) (code) (baz)) - - -- 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 - - -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) - - -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 lists) - Return a new list with the concatenation of the elements in the - supplied LISTS. - - (-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) - Return a list with element at Nth position in LIST replaced with - ‘(func (nth n list))‘. - - 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 a list with element at Nth position in LIST removed. - - See also: ‘-remove-at-indices’ (*note -remove-at-indices::), - ‘-remove’ (*note -remove::) - - (-remove-at 0 '("0" "1" "2" "3" "4" "5")) - ⇒ ("1" "2" "3" "4" "5") - (-remove-at 1 '("0" "1" "2" "3" "4" "5")) - ⇒ ("0" "2" "3" "4" "5") - (-remove-at 2 '("0" "1" "2" "3" "4" "5")) - ⇒ ("0" "1" "3" "4" "5") - - -- Function: -remove-at-indices (indices list) - Return a list whose elements are elements from LIST without - elements selected as ‘(nth i list)‘ for all i from INDICES. - - See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note - -remove::) - - (-remove-at-indices '(0) '("0" "1" "2" "3" "4" "5")) - ⇒ ("1" "2" "3" "4" "5") - (-remove-at-indices '(0 2 4) '("0" "1" "2" "3" "4" "5")) - ⇒ ("1" "3" "5") - (-remove-at-indices '(0 5) '("0" "1" "2" "3" "4" "5")) - ⇒ ("1" "2" "3" "4") - - -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) - - -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)) - - -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 at least one item of LIST matches PRED and at least - one item of LIST does not match PRED. Return ‘nil‘ both if all - items match the predicate or if none of the items match the - predicate. - - 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’s non-nil. - - Alias: ‘-contains-p’ - - (-contains? '(1 2 3) 1) - ⇒ t - (-contains? '(1 2 3) 2) - ⇒ t - (-contains? '(1 2 3) 4) - ⇒ nil - - -- Function: -same-items? (list list2) - Return true if LIST and LIST2 has the same items. - - The order of the elements in the lists does not matter. - - Alias: ‘-same-items-p’ - - (-same-items? '(1 2 3) '(1 2 3)) - ⇒ t - (-same-items? '(1 2 3) '(3 2 1)) - ⇒ t - (-same-items? '(1 2 3) '(1 2 3 4)) - ⇒ nil - - -- 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 - - -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) - Return a list of ((-take-while PRED LIST) (-drop-while PRED LIST)), - in no more than one pass through the 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) - Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one - pass through the 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) - Return a new list with the items in LIST grouped into N-sized - sublists at offsets STEP apart. 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) - Return a new list with the items in LIST grouped into N-sized - sublists at offsets STEP apart. The last 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")) - - -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 index of the first element in the given LIST which is - equal to the query element ELEM, or nil if there is no such - element. - - (-elem-index 2 '(6 7 8 2 3 4)) - ⇒ 3 - (-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 indices of all elements in LIST equal to the query - element ELEM, in ascending order. - - (-elem-indices 2 '(6 7 8 2 3 4 2 1)) - ⇒ (3 6) - (-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) - Take a predicate PRED and a LIST and return the index of the first - element in the list satisfying the predicate, or nil if there is no - such element. - - See also ‘-first’ (*note -first::). - - (-find-index 'even? '(2 4 1 6 3 3 5 8)) - ⇒ 0 - (--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) - ⇒ 3 - (-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) - ⇒ 1 - - -- Function: -find-last-index (pred list) - Take a predicate PRED and a LIST and return the index of the last - element in the list satisfying the predicate, or nil if there is no - such element. - - See also ‘-last’ (*note -last::). - - (-find-last-index 'even? '(2 4 1 6 3 3 5 8)) - ⇒ 7 - (--find-last-index (< 5 it) '(2 7 1 6 3 8 5 2)) - ⇒ 5 - (-find-last-index (-partial 'string-lessp "baz") '("q" "foo" "baz")) - ⇒ 1 - - -- Function: -find-indices (pred list) - Return the indices of all elements in LIST satisfying the predicate - PRED, in ascending order. - - (-find-indices 'even? '(2 4 1 6 3 3 5 8)) - ⇒ (0 1 3 7) - (--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) - ⇒ (3 7) - (-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) - ⇒ (1) - - -- 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) - - -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 (list list2) - Return a new list containing the elements of LIST and elements of - LIST2 that are not in LIST. The test for equality is done with - ‘equal’, or with ‘-compare-fn’ if that’s non-nil. - - (-union '(1 2 3) '(3 4 5)) - ⇒ (1 2 3 4 5) - (-union '(1 2 3 4) ()) - ⇒ (1 2 3 4) - (-union '(1 1 2 2) '(3 2 1)) - ⇒ (1 1 2 2 3) - - -- Function: -difference (list list2) - Return a new list with only the members of LIST that are not in - LIST2. The test for equality is done with ‘equal’, or with - ‘-compare-fn’ if that’s 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 (list list2) - Return a new list containing only the elements that are members of - both LIST and LIST2. The test for equality is done with ‘equal’, - or with ‘-compare-fn’ if that’s non-nil. - - (-intersection () ()) - ⇒ () - (-intersection '(1 2 3) '(4 5 6)) - ⇒ () - (-intersection '(1 2 3 4) '(3 4 5 6)) - ⇒ (3 4) - - -- Function: -powerset (list) - Return the power set of LIST. - - (-powerset ()) - ⇒ (nil) - (-powerset '(x y z)) - ⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil) - - -- Function: -permutations (list) - Return the permutations of LIST. - - (-permutations ()) - ⇒ (nil) - (-permutations '(1 2)) - ⇒ ((1 2) (2 1)) - (-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 new list with all duplicates removed. The test for - equality is done with ‘equal’, or with ‘-compare-fn’ if that’s - non-nil. - - Alias: ‘-uniq’ - - (-distinct ()) - ⇒ () - (-distinct '(1 2 2 4)) - ⇒ (1 2 4) - (-distinct '(t t t)) - ⇒ (t) - - -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: -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) - ⇒ nil - - -- 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 ELEMENTS is non nil, append these 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 the two lists LIST1 and LIST2 using a function FN. This - function is applied pairwise taking as first argument element of - LIST1 and as second argument element of LIST2 at corresponding - position. - - The anaphoric form ‘--zip-with’ binds the elements from LIST1 as - symbol ‘it’, and the elements from LIST2 as symbol ‘other’. - - (-zip-with '+ '(1 2 3) '(4 5 6)) - ⇒ (5 7 9) - (-zip-with 'cons '(1 2 3) '(4 5 6)) - ⇒ ((1 . 4) (2 . 5) (3 . 6)) - (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) - ⇒ ("Batman and Robin" "Jekyll and Hyde") - - -- Function: -zip (&rest lists) - Zip LISTS together. Group the head of each list, followed by the - second elements of each list, and so on. The lengths of the - returned groupings are equal to the length of the shortest input - list. - - If two lists are provided as arguments, return the groupings as a - list of cons cells. Otherwise, return the groupings as a list of - lists. - - Use ‘-zip-lists’ (*note -zip-lists::) if you need the return value - to always be a list of lists. - - Alias: ‘-zip-pair’ - - See also: ‘-zip-lists’ (*note -zip-lists::) - - (-zip '(1 2 3) '(4 5 6)) - ⇒ ((1 . 4) (2 . 5) (3 . 6)) - (-zip '(1 2 3) '(4 5 6 7)) - ⇒ ((1 . 4) (2 . 5) (3 . 6)) - (-zip '(1 2) '(3 4 5) '(6)) - ⇒ ((1 3 6)) - - -- Function: -zip-lists (&rest lists) - Zip LISTS together. Group the head of each list, followed by the - second elements of each list, and so on. The lengths of the - returned groupings are equal to the length of the shortest input - list. - - The return value is always list of lists, which is a difference - from ‘-zip-pair’ which returns a cons-cell in case two input lists - are provided. - - See also: ‘-zip’ (*note -zip::) - - (-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-fill (fill-value &rest lists) - Zip LISTS, with FILL-VALUE padded onto the shorter lists. The - lengths of the returned groupings are equal to the length of the - longest input list. - - (-zip-fill 0 '(1 2 3 4 5) '(6 7 8 9)) - ⇒ ((1 . 6) (2 . 7) (3 . 8) (4 . 9) (5 . 0)) - - -- Function: -unzip (lists) - Unzip LISTS. - - This works just like ‘-zip’ (*note -zip::) 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 the same length). - - Note in particular that calling this on a list of two lists will - return a list of cons-cells such that the above identity works. - - See also: ‘-zip’ (*note -zip::) - - (-unzip (-zip '(1 2 3) '(a b c) '("e" "f" "g"))) - ⇒ ((1 2 3) (a b c) ("e" "f" "g")) - (-unzip '((1 2) (3 4) (5 6) (7 8) (9 10))) - ⇒ ((1 3 5 7 9) (2 4 6 8 10)) - (-unzip '((1 2) (3 4))) - ⇒ ((1 . 3) (2 . 4)) - - -- 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 (-cycle '(1 2 3)) '(1 2)) - ⇒ ((1 . 1) (2 . 2)) - - -- Function: -pad (fill-value &rest lists) - Appends FILL-VALUE to the end of each list in LISTS such that they - will all have the same length. - - (-pad 0 ()) - ⇒ (nil) - (-pad 0 '(1)) - ⇒ ((1)) - (-pad 0 '(1 2 3) '(4 5)) - ⇒ ((1 2 3) (4 5 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 ‘car’. - - 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::). - - (-first-item '(1 2 3)) - ⇒ 1 - (-first-item nil) - ⇒ nil - (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: ‘-third-item’ (*note -third-item::). - - (-second-item '(1 2 3)) - ⇒ 2 - (-second-item nil) - ⇒ nil - - -- Function: -third-item (list) - Return the third item of LIST, or nil if LIST is too short. - - See also: ‘-fourth-item’ (*note -fourth-item::). - - (-third-item '(1 2 3)) - ⇒ 3 - (-third-item nil) - ⇒ nil - - -- Function: -fourth-item (list) - Return the fourth item of LIST, or nil if LIST is too short. - - See also: ‘-fifth-item’ (*note -fifth-item::). - - (-fourth-item '(1 2 3 4)) - ⇒ 4 - (-fourth-item nil) - ⇒ nil - - -- Function: -fifth-item (list) - Return the fifth item of LIST, or nil if LIST is too short. - - See also: ‘-last-item’ (*note -last-item::). - - (-fifth-item '(1 2 3 4 5)) - ⇒ 5 - (-fifth-item nil) - ⇒ nil - - -- Function: -last-item (list) - Return the last item of LIST, or nil on an empty list. - - (-last-item '(1 2 3)) - ⇒ 3 - (-last-item nil) - ⇒ nil - (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) - - -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 '(1 2 3)) (b (-clone a))) (nreverse a) b) - ⇒ (1 2 3) - - -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 in 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 - - -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" - - -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) - - -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) - - -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) - Take a list of n functions and return a function that takes a list - of length n, applying i-th function to i-th 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) (7 8))) - ⇒ ((2 1) (4 3) (6 5) (8 7)) - (apply '+ (funcall (-prodfn 'length 'string-to-number) '((1 2 3) "15"))) - ⇒ 18 - - -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. - - -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::. - - -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::. - - -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. - - -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>. - - -File: dash.info, Node: Index, Prev: GPL, Up: Top - -Index -***** - - -* 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 84) -* -any?: Predicates. (line 41) -* -applify: Function combinators. - (line 63) -* -as->: Threading macros. (line 49) -* -butlast: Other list operations. - (line 335) -* -clone: Tree operations. (line 122) -* -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 30) -* -cons-pair?: Predicates. (line 167) -* -const: Function combinators. - (line 128) -* -contains?: Predicates. (line 100) -* -copy: Maps. (line 139) -* -count: Reductions. (line 172) -* -cut: Function combinators. - (line 140) -* -cycle: Other list operations. - (line 180) -* -difference: Set operations. (line 20) -* -distinct: Set operations. (line 62) -* -dotimes: Side effects. (line 80) -* -doto: Threading macros. (line 99) -* -drop: Sublist selection. (line 147) -* -drop-last: Sublist selection. (line 161) -* -drop-while: Sublist selection. (line 192) -* -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 21) -* -every: Predicates. (line 23) -* -fifth-item: Other list operations. - (line 315) -* -filter: Sublist selection. (line 8) -* -find-index: Indexing. (line 32) -* -find-indices: Indexing. (line 60) -* -find-last-index: Indexing. (line 46) -* -first: Other list operations. - (line 246) -* -first-item: Other list operations. - (line 272) -* -fix: Other list operations. - (line 375) -* -fixfn: Function combinators. - (line 224) -* -flatten: List to list. (line 34) -* -flatten-n: List to list. (line 56) -* -flip: Function combinators. - (line 95) -* -fourth-item: Other list operations. - (line 305) -* -grade-down: Indexing. (line 81) -* -grade-up: Indexing. (line 71) -* -group-by: Partitioning. (line 194) -* -if-let: Binding. (line 34) -* -if-let*: Binding. (line 45) -* -inits: Reductions. (line 222) -* -insert-at: List to list. (line 110) -* -interleave: Other list operations. - (line 67) -* -interpose: Other list operations. - (line 57) -* -intersection: Set operations. (line 32) -* -iota: Other list operations. - (line 78) -* -is-infix?: Predicates. (line 153) -* -is-prefix?: Predicates. (line 129) -* -is-suffix?: Predicates. (line 141) -* -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 262) -* -last-item: Other list operations. - (line 325) -* -let: Binding. (line 61) -* -let*: Binding. (line 227) -* -list: Other list operations. - (line 358) -* -map: Maps. (line 10) -* -map-first: Maps. (line 38) -* -map-indexed: Maps. (line 66) -* -map-last: Maps. (line 52) -* -map-when: Maps. (line 22) -* -mapcat: Maps. (line 128) -* -max: Reductions. (line 286) -* -max-by: Reductions. (line 296) -* -min: Reductions. (line 262) -* -min-by: Reductions. (line 272) -* -non-nil: Sublist selection. (line 94) -* -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 191) -* -partial: Function combinators. - (line 8) -* -partition: Partitioning. (line 80) -* -partition-after-item: Partitioning. (line 184) -* -partition-after-pred: Partitioning. (line 151) -* -partition-all: Partitioning. (line 92) -* -partition-all-in-steps: Partitioning. (line 115) -* -partition-before-item: Partitioning. (line 174) -* -partition-before-pred: Partitioning. (line 163) -* -partition-by: Partitioning. (line 127) -* -partition-by-header: Partitioning. (line 138) -* -partition-in-steps: Partitioning. (line 103) -* -permutations: Set operations. (line 52) -* -powerset: Set operations. (line 44) -* -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 146) -* -remove-at-indices: List to list. (line 159) -* -remove-first: Sublist selection. (line 43) -* -remove-item: Sublist selection. (line 83) -* -remove-last: Sublist selection. (line 64) -* -repeat: Other list operations. - (line 19) -* -replace: List to list. (line 68) -* -replace-at: List to list. (line 121) -* -replace-first: List to list. (line 82) -* -replace-last: List to list. (line 96) -* -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?: Predicates. (line 115) -* -second-item: Other list operations. - (line 285) -* -select-by-indices: Sublist selection. (line 208) -* -select-column: Sublist selection. (line 238) -* -select-columns: Sublist selection. (line 219) -* -separate: Partitioning. (line 69) -* -setq: Binding. (line 270) -* -slice: Sublist selection. (line 104) -* -snoc: Other list operations. - (line 43) -* -some: Predicates. (line 8) -* -some-->: Threading macros. (line 86) -* -some->: Threading macros. (line 62) -* -some->>: Threading macros. (line 74) -* -sort: Other list operations. - (line 345) -* -splice: Maps. (line 95) -* -splice-list: Maps. (line 115) -* -split-at: Partitioning. (line 8) -* -split-on: Partitioning. (line 34) -* -split-when: Partitioning. (line 52) -* -split-with: Partitioning. (line 23) -* -sum: Reductions. (line 180) -* -table: Other list operations. - (line 202) -* -table-flat: Other list operations. - (line 221) -* -tails: Reductions. (line 232) -* -take: Sublist selection. (line 120) -* -take-last: Sublist selection. (line 133) -* -take-while: Sublist selection. (line 175) -* -third-item: Other list operations. - (line 295) -* -tree-map: Tree operations. (line 28) -* -tree-map-nodes: Tree operations. (line 39) -* -tree-mapreduce: Tree operations. (line 84) -* -tree-mapreduce-from: Tree operations. (line 103) -* -tree-reduce: Tree operations. (line 52) -* -tree-reduce-from: Tree operations. (line 69) -* -tree-seq: Tree operations. (line 8) -* -unfold: Unfolding. (line 25) -* -union: Set operations. (line 8) -* -unzip: Other list operations. - (line 158) -* -update-at: List to list. (line 133) -* -when-let: Binding. (line 9) -* -when-let*: Binding. (line 21) -* -zip: Other list operations. - (line 107) -* -zip-fill: Other list operations. - (line 150) -* -zip-lists: Other list operations. - (line 131) -* -zip-with: Other list operations. - (line 91) -* 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) - - - -Tag Table: -Node: Top742 -Node: Installation2397 -Node: Using in a package3159 -Node: Fontification of special variables3504 -Node: Info symbol lookup4294 -Node: Functions4877 -Node: Maps6361 -Ref: -map6658 -Ref: -map-when7031 -Ref: -map-first7606 -Ref: -map-last8081 -Ref: -map-indexed8551 -Ref: -annotate9237 -Ref: -splice9724 -Ref: -splice-list10502 -Ref: -mapcat10961 -Ref: -copy11334 -Node: Sublist selection11522 -Ref: -filter11715 -Ref: -remove12262 -Ref: -remove-first12800 -Ref: -remove-last13642 -Ref: -remove-item14367 -Ref: -non-nil14767 -Ref: -slice15043 -Ref: -take15572 -Ref: -take-last15979 -Ref: -drop16410 -Ref: -drop-last16851 -Ref: -take-while17277 -Ref: -drop-while17892 -Ref: -select-by-indices18508 -Ref: -select-columns19019 -Ref: -select-column19722 -Node: List to list20185 -Ref: -keep20377 -Ref: -concat20941 -Ref: -flatten21235 -Ref: -flatten-n21991 -Ref: -replace22375 -Ref: -replace-first22836 -Ref: -replace-last23331 -Ref: -insert-at23819 -Ref: -replace-at24144 -Ref: -update-at24531 -Ref: -remove-at25019 -Ref: -remove-at-indices25504 -Node: Reductions26083 -Ref: -reduce-from26279 -Ref: -reduce-r-from27003 -Ref: -reduce28266 -Ref: -reduce-r29017 -Ref: -reductions-from30295 -Ref: -reductions-r-from31101 -Ref: -reductions31931 -Ref: -reductions-r32642 -Ref: -count33387 -Ref: -sum33611 -Ref: -running-sum33799 -Ref: -product34120 -Ref: -running-product34328 -Ref: -inits34669 -Ref: -tails34914 -Ref: -common-prefix35158 -Ref: -common-suffix35452 -Ref: -min35746 -Ref: -min-by35972 -Ref: -max36493 -Ref: -max-by36718 -Node: Unfolding37244 -Ref: -iterate37485 -Ref: -unfold37932 -Node: Predicates38737 -Ref: -some38914 -Ref: -every39331 -Ref: -any?40010 -Ref: -all?40341 -Ref: -none?41048 -Ref: -only-some?41350 -Ref: -contains?41835 -Ref: -same-items?42224 -Ref: -is-prefix?42609 -Ref: -is-suffix?42935 -Ref: -is-infix?43261 -Ref: -cons-pair?43615 -Node: Partitioning43940 -Ref: -split-at44128 -Ref: -split-with44792 -Ref: -split-on45192 -Ref: -split-when45863 -Ref: -separate46500 -Ref: -partition46939 -Ref: -partition-all47388 -Ref: -partition-in-steps47813 -Ref: -partition-all-in-steps48307 -Ref: -partition-by48789 -Ref: -partition-by-header49167 -Ref: -partition-after-pred49768 -Ref: -partition-before-pred50215 -Ref: -partition-before-item50600 -Ref: -partition-after-item50907 -Ref: -group-by51209 -Node: Indexing51642 -Ref: -elem-index51844 -Ref: -elem-indices52239 -Ref: -find-index52619 -Ref: -find-last-index53108 -Ref: -find-indices53612 -Ref: -grade-up54017 -Ref: -grade-down54424 -Node: Set operations54838 -Ref: -union55021 -Ref: -difference55459 -Ref: -intersection55871 -Ref: -powerset56303 -Ref: -permutations56513 -Ref: -distinct56809 -Node: Other list operations57183 -Ref: -rotate57408 -Ref: -repeat57761 -Ref: -cons*58040 -Ref: -snoc58456 -Ref: -interpose58866 -Ref: -interleave59160 -Ref: -iota59526 -Ref: -zip-with60009 -Ref: -zip60723 -Ref: -zip-lists61552 -Ref: -zip-fill62250 -Ref: -unzip62572 -Ref: -cycle63314 -Ref: -pad63713 -Ref: -table64032 -Ref: -table-flat64818 -Ref: -first65823 -Ref: -last66309 -Ref: -first-item66643 -Ref: -second-item67042 -Ref: -third-item67306 -Ref: -fourth-item67568 -Ref: -fifth-item67834 -Ref: -last-item68096 -Ref: -butlast68387 -Ref: -sort68632 -Ref: -list69118 -Ref: -fix69687 -Node: Tree operations70176 -Ref: -tree-seq70372 -Ref: -tree-map71227 -Ref: -tree-map-nodes71667 -Ref: -tree-reduce72514 -Ref: -tree-reduce-from73396 -Ref: -tree-mapreduce73996 -Ref: -tree-mapreduce-from74855 -Ref: -clone76140 -Node: Threading macros76467 -Ref: ->76692 -Ref: ->>77180 -Ref: -->77683 -Ref: -as->78239 -Ref: -some->78693 -Ref: -some->>79066 -Ref: -some-->79501 -Ref: -doto80050 -Node: Binding80603 -Ref: -when-let80810 -Ref: -when-let*81265 -Ref: -if-let81788 -Ref: -if-let*82148 -Ref: -let82765 -Ref: -let*88837 -Ref: -lambda89774 -Ref: -setq90580 -Node: Side effects91381 -Ref: -each91575 -Ref: -each-while92096 -Ref: -each-indexed92698 -Ref: -each-r93284 -Ref: -each-r-while93720 -Ref: -dotimes94346 -Node: Destructive operations94899 -Ref: !cons95117 -Ref: !cdr95321 -Node: Function combinators95514 -Ref: -partial95718 -Ref: -rpartial96236 -Ref: -juxt96884 -Ref: -compose97336 -Ref: -applify97943 -Ref: -on98373 -Ref: -flip99145 -Ref: -rotate-args99669 -Ref: -const100298 -Ref: -cut100640 -Ref: -not101120 -Ref: -orfn101646 -Ref: -andfn102408 -Ref: -iteratefn103164 -Ref: -fixfn103866 -Ref: -prodfn105422 -Node: Development106480 -Node: Contribute106769 -Node: Contributors107781 -Node: FDL109874 -Node: GPL135194 -Node: Index172943 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/dash-20210826.1149/dir b/elpa/dash-20210826.1149/dir deleted file mode 100644 index 7d473f4..0000000 --- a/elpa/dash-20210826.1149/dir +++ /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. - -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. |