diff options
Diffstat (limited to 'elpa/dash-20200524.1947')
-rw-r--r-- | elpa/dash-20200524.1947/dash-autoloads.el | 26 | ||||
-rw-r--r-- | elpa/dash-20200524.1947/dash-pkg.el | 9 | ||||
-rw-r--r-- | elpa/dash-20200524.1947/dash.el | 3072 | ||||
-rw-r--r-- | elpa/dash-20200524.1947/dash.info | 3410 | ||||
-rw-r--r-- | elpa/dash-20200524.1947/dir | 18 |
5 files changed, 0 insertions, 6535 deletions
diff --git a/elpa/dash-20200524.1947/dash-autoloads.el b/elpa/dash-20200524.1947/dash-autoloads.el deleted file mode 100644 index c5e7902..0000000 --- a/elpa/dash-20200524.1947/dash-autoloads.el +++ /dev/null @@ -1,26 +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 - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dash" '("dash-" "-keep" "-butlast" "-non" "-only-some" "-zip" "-e" "->" "-a" "-gr" "-when-let" "-d" "-l" "-s" "-p" "-r" "-m" "-i" "-f" "-u" "-value-to-list" "-t" "--" "-c" "!cons" "!cdr"))) - -;;;*** - -;;;### (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-20200524.1947/dash-pkg.el b/elpa/dash-20200524.1947/dash-pkg.el deleted file mode 100644 index 08d8982..0000000 --- a/elpa/dash-20200524.1947/dash-pkg.el +++ /dev/null @@ -1,9 +0,0 @@ -(define-package "dash" "20200524.1947" "A modern list library for Emacs" 'nil :commit "732d92eac56023a4fb4a5dc3d9d4e274ebf44bf9" :keywords - '("lists") - :authors - '(("Magnar Sveen" . "magnars@gmail.com")) - :maintainer - '("Magnar Sveen" . "magnars@gmail.com")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/dash-20200524.1947/dash.el b/elpa/dash-20200524.1947/dash.el deleted file mode 100644 index 1fc2ec8..0000000 --- a/elpa/dash-20200524.1947/dash.el +++ /dev/null @@ -1,3072 +0,0 @@ -;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*- - -;; Copyright (C) 2012-2016 Free Software Foundation, Inc. - -;; Author: Magnar Sveen <magnars@gmail.com> -;; Version: 2.17.0 -;; Keywords: lists - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Commentary: - -;; A modern list api for Emacs. -;; -;; See documentation on https://github.com/magnars/dash.el#functions -;; -;; **Please note** The lexical binding in this file is not utilised at the -;; moment. We will take full advantage of lexical binding in an upcoming 3.0 -;; release of Dash. In the meantime, we've added the pragma to avoid a bug that -;; you can read more about in https://github.com/magnars/dash.el/issues/130. -;; - -;;; 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.el" - :group 'lisp - :prefix "dash-") - -(defun dash--enable-fontlock (symbol value) - (when value - (dash-enable-font-lock)) - (set-default symbol value)) - -(defcustom dash-enable-fontlock nil - "If non-nil, enable fontification of dash functions, macros and -special values." - :type 'boolean - :set 'dash--enable-fontlock - :group 'dash) - -(defmacro !cons (car cdr) - "Destructive: Set CDR to the cons of CAR and CDR." - `(setq ,cdr (cons ,car ,cdr))) - -(defmacro !cdr (list) - "Destructive: Set LIST to the cdr of LIST." - `(setq ,list (cdr ,list))) - -(defmacro --each (list &rest body) - "Anaphoric form of `-each'." - (declare (debug (form body)) - (indent 1)) - (let ((l (make-symbol "list"))) - `(let ((,l ,list) - (it-index 0)) - (while ,l - (let ((it (car ,l))) - ,@body) - (setq it-index (1+ it-index)) - (!cdr ,l))))) - -(defmacro -doto (eval-initial-value &rest forms) - "Eval a form, then insert that form as the 2nd argument to other forms. -The EVAL-INITIAL-VALUE form is evaluated once. Its result is -passed to FORMS, which are then evaluated sequentially. Returns -the target form." - (declare (indent 1)) - (let ((retval (make-symbol "value"))) - `(let ((,retval ,eval-initial-value)) - ,@(mapcar (lambda (form) - (if (sequencep form) - `(,(-first-item form) ,retval ,@(cdr form)) - `(funcall form ,retval))) - forms) - ,retval))) - -(defmacro --doto (eval-initial-value &rest forms) - "Anaphoric form of `-doto'. -Note: `it' is not required in each form." - (declare (indent 1)) - `(let ((it ,eval-initial-value)) - ,@forms - it)) - -(defun -each (list fn) - "Call FN with every item in LIST. Return nil, used for side-effects only." - (--each list (funcall fn it))) - -(put '-each 'lisp-indent-function 1) - -(defalias '--each-indexed '--each) - -(defun -each-indexed (list fn) - "Call (FN index item) for each item in LIST. - -In the anaphoric form `--each-indexed', the index is exposed as symbol `it-index'. - -See also: `-map-indexed'." - (--each list (funcall fn it-index it))) -(put '-each-indexed 'lisp-indent-function 1) - -(defmacro --each-while (list pred &rest body) - "Anaphoric form of `-each-while'." - (declare (debug (form form body)) - (indent 2)) - (let ((l (make-symbol "list")) - (c (make-symbol "continue"))) - `(let ((,l ,list) - (,c t) - (it-index 0)) - (while (and ,l ,c) - (let ((it (car ,l))) - (if (not ,pred) (setq ,c nil) ,@body)) - (setq it-index (1+ it-index)) - (!cdr ,l))))) - -(defun -each-while (list pred fn) - "Call FN with every item in LIST while (PRED item) is non-nil. -Return nil, used for side-effects only." - (--each-while list (funcall pred it) (funcall fn it))) - -(put '-each-while 'lisp-indent-function 2) - -(defmacro --each-r (list &rest body) - "Anaphoric form of `-each-r'." - (declare (debug (form body)) - (indent 1)) - (let ((v (make-symbol "vector"))) - ;; Implementation note: building 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 modification was reversed before we return. - `(let* ((,v (vconcat ,list)) - (it-index (length ,v)) - it) - (while (> it-index 0) - (setq it-index (1- it-index)) - (setq it (aref ,v it-index)) - ,@body)))) - -(defun -each-r (list fn) - "Call FN with every item in LIST in reversed order. - Return nil, used for side-effects only." - (--each-r list (funcall fn it))) - -(defmacro --each-r-while (list pred &rest body) - "Anaphoric form of `-each-r-while'." - (declare (debug (form form body)) - (indent 2)) - (let ((v (make-symbol "vector"))) - `(let* ((,v (vconcat ,list)) - (it-index (length ,v)) - it) - (while (> it-index 0) - (setq it-index (1- it-index)) - (setq it (aref ,v it-index)) - (if (not ,pred) - (setq it-index -1) - ,@body))))) - -(defun -each-r-while (list pred fn) - "Call FN with every item in reversed LIST while (PRED item) is non-nil. -Return nil, used for side-effects only." - (--each-r-while list (funcall pred it) (funcall fn it))) - -(defmacro --dotimes (num &rest body) - "Repeatedly executes BODY (presumably for side-effects) with symbol `it' bound to integers from 0 through NUM-1." - (declare (debug (form body)) - (indent 1)) - (let ((n (make-symbol "num"))) - `(let ((,n ,num) - (it 0)) - (while (< it ,n) - ,@body - (setq it (1+ it)))))) - -(defun -dotimes (num fn) - "Repeatedly calls FN (presumably for side-effects) passing in integers from 0 through NUM-1." - (--dotimes num (funcall fn it))) - -(put '-dotimes 'lisp-indent-function 1) - -(defun -map (fn list) - "Return a new list consisting of the result of applying FN to the items in LIST." - (mapcar fn list)) - -(defmacro --map (form list) - "Anaphoric form of `-map'." - (declare (debug (form form))) - `(mapcar (lambda (it) ,form) ,list)) - -(defmacro --reduce-from (form initial-value list) - "Anaphoric form of `-reduce-from'." - (declare (debug (form form form))) - `(let ((acc ,initial-value)) - (--each ,list (setq acc ,form)) - acc)) - -(defun -reduce-from (fn initial-value list) - "Return the result of applying FN to INITIAL-VALUE and the -first item in LIST, then applying FN to that result and the 2nd -item, etc. If LIST contains no items, return INITIAL-VALUE and -do not call FN. - -In the anaphoric form `--reduce-from', the accumulated value is -exposed as symbol `acc'. - -See also: `-reduce', `-reduce-r'" - (--reduce-from (funcall fn acc it) initial-value list)) - -(defmacro --reduce (form list) - "Anaphoric form of `-reduce'." - (declare (debug (form form))) - (let ((lv (make-symbol "list-value"))) - `(let ((,lv ,list)) - (if ,lv - (--reduce-from ,form (car ,lv) (cdr ,lv)) - (let (acc it) ,form))))) - -(defun -reduce (fn list) - "Return the result of applying FN to the first 2 items in LIST, -then applying FN to that result and the 3rd item, etc. If LIST -contains no items, return the result of calling FN with no -arguments. If LIST contains a single item, return that item -and do not call FN. - -In the anaphoric form `--reduce', the accumulated value is -exposed as symbol `acc'. - -See also: `-reduce-from', `-reduce-r'" - (if list - (-reduce-from fn (car list) (cdr list)) - (funcall fn))) - -(defmacro --reduce-r-from (form initial-value list) - "Anaphoric version of `-reduce-r-from'." - (declare (debug (form form form))) - `(--reduce-from ,form ,initial-value (reverse ,list))) - -(defun -reduce-r-from (fn initial-value list) - "Replace conses with FN, nil with INITIAL-VALUE and evaluate -the resulting expression. If LIST is empty, INITIAL-VALUE is -returned and FN is not called. - -Note: this function works the same as `-reduce-from' but the -operation associates from right instead of from left. - -See also: `-reduce-r', `-reduce'" - (--reduce-r-from (funcall fn it acc) initial-value list)) - -(defmacro --reduce-r (form list) - "Anaphoric version of `-reduce-r'." - (declare (debug (form form))) - `(--reduce ,form (reverse ,list))) - -(defun -reduce-r (fn list) - "Replace conses with FN and evaluate the resulting expression. -The final nil is ignored. If LIST contains no items, return the -result of calling FN with no arguments. If LIST contains a single -item, return that item and do not call FN. - -The first argument of FN is the new item, the second is the -accumulated value. - -Note: this function works the same as `-reduce' but the operation -associates from right instead of from left. - -See also: `-reduce-r-from', `-reduce'" - (if list - (--reduce-r (funcall fn it acc) list) - (funcall fn))) - -(defun -reductions-from (fn init list) - "Return a list of the intermediate values of the reduction. - -See `-reduce-from' for explanation of the arguments. - -See also: `-reductions', `-reductions-r', `-reduce-r'" - (nreverse (--reduce-from (cons (funcall fn (car acc) it) acc) (list init) list))) - -(defun -reductions (fn list) - "Return a list of the intermediate values of the reduction. - -See `-reduce' for explanation of the arguments. - -See also: `-reductions-from', `-reductions-r', `-reduce-r'" - (and list (-reductions-from fn (car list) (cdr list)))) - -(defun -reductions-r-from (fn init list) - "Return a list of the intermediate values of the reduction. - -See `-reduce-r-from' for explanation of the arguments. - -See also: `-reductions-r', `-reductions', `-reduce'" - (--reduce-r-from (cons (funcall fn it (car acc)) acc) (list init) list)) - -(defun -reductions-r (fn list) - "Return a list of the intermediate values of the reduction. - -See `-reduce-r' for explanation of the arguments. - -See also: `-reductions-r-from', `-reductions', `-reduce'" - (when list - (let ((rev (reverse list))) - (--reduce-from (cons (funcall fn it (car acc)) acc) - (list (car rev)) - (cdr rev))))) - -(defmacro --filter (form list) - "Anaphoric form of `-filter'. - -See also: `--remove'." - (declare (debug (form form))) - (let ((r (make-symbol "result"))) - `(let (,r) - (--each ,list (when ,form (!cons it ,r))) - (nreverse ,r)))) - -(defun -filter (pred list) - "Return a new list of the items in LIST for which PRED returns a non-nil value. - -Alias: `-select' - -See also: `-keep', `-remove'." - (--filter (funcall pred it) list)) - -(defalias '-select '-filter) -(defalias '--select '--filter) - -(defmacro --remove (form list) - "Anaphoric form of `-remove'. - -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' - -See also: `-filter'." - (--remove (funcall pred it) list)) - -(defalias '-reject '-remove) -(defalias '--reject '--remove) - -(defun -remove-first (pred list) - "Return a new list with the first item matching PRED removed. - -Alias: `-reject-first' - -See also: `-remove', `-map-first'" - (let (front) - (while (and list (not (funcall pred (car list)))) - (push (car list) front) - (!cdr list)) - (if list - (-concat (nreverse front) (cdr list)) - (nreverse front)))) - -(defmacro --remove-first (form list) - "Anaphoric form of `-remove-first'." - (declare (debug (form form))) - `(-remove-first (lambda (it) ,form) ,list)) - -(defalias '-reject-first '-remove-first) -(defalias '--reject-first '--remove-first) - -(defun -remove-last (pred list) - "Return a new list with the last item matching PRED removed. - -Alias: `-reject-last' - -See also: `-remove', `-map-last'" - (nreverse (-remove-first pred (reverse list)))) - -(defmacro --remove-last (form list) - "Anaphoric form of `-remove-last'." - (declare (debug (form form))) - `(-remove-last (lambda (it) ,form) ,list)) - -(defalias '-reject-last '-remove-last) -(defalias '--reject-last '--remove-last) - -(defun -remove-item (item list) - "Remove all occurrences of ITEM from LIST. - -Comparison is done with `equal'." - (declare (pure t) (side-effect-free t)) - (--remove (equal it item) list)) - -(defmacro --keep (form list) - "Anaphoric form of `-keep'." - (declare (debug (form form))) - (let ((r (make-symbol "result")) - (m (make-symbol "mapped"))) - `(let (,r) - (--each ,list (let ((,m ,form)) (when ,m (!cons ,m ,r)))) - (nreverse ,r)))) - -(defun -keep (fn list) - "Return a new list of the non-nil results of applying FN to the items in LIST. - -If you want to select the original items satisfying a predicate use `-filter'." - (--keep (funcall fn it) list)) - -(defun -non-nil (list) - "Return all non-nil elements of LIST." - (declare (pure t) (side-effect-free t)) - (-remove 'null list)) - -(defmacro --map-indexed (form list) - "Anaphoric form of `-map-indexed'." - (declare (debug (form form))) - (let ((r (make-symbol "result"))) - `(let (,r) - (--each ,list - (!cons ,form ,r)) - (nreverse ,r)))) - -(defun -map-indexed (fn list) - "Return a new list consisting of the result of (FN index item) for each item in LIST. - -In the anaphoric form `--map-indexed', the index is exposed as symbol `it-index'. - -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'." - `(-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'." - `(-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)) - -(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))) - -(defmacro --iterate (form init n) - "Anaphoric version of `-iterate'." - (declare (debug (form form form))) - `(-iterate (lambda (it) ,form) ,init ,n)) - -(defun -flatten-n (num list) - "Flatten NUM levels of a nested LIST. - -See also: `-flatten'" - (declare (pure t) (side-effect-free t)) - (-last-item (--iterate (--mapcat (-list it) it) list (1+ num)))) - -(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'." - `(-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'." - `(-splice-list (lambda (it) ,pred) ,new-list ,list)) - -(defun -cons* (&rest args) - "Make a new list from the elements of ARGS. - -The last 2 members of ARGS are used as the final cons of the -result so if the final member of ARGS is not a list the result is -a dotted list." - (declare (pure t) (side-effect-free t)) - (-reduce-r 'cons 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) - "Anaphoric form of `-first'." - (declare (debug (form form))) - (let ((n (make-symbol "needle"))) - `(let (,n) - (--each-while ,list (not ,n) - (when ,form (setq ,n it))) - ,n))) - -(defun -first (pred list) - "Return the first x in LIST where (PRED x) is non-nil, else nil. - -To get the first item in the list no questions asked, use `car'. - -Alias: `-find'" - (--first (funcall pred it) list)) - -(defalias '-find '-first) -(defalias '--find '--first) - -(defmacro --some (form list) - "Anaphoric form of `-some'." - (declare (debug (form form))) - (let ((n (make-symbol "needle"))) - `(let (,n) - (--each-while ,list (not ,n) - (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'" - (--some (funcall pred it) list)) - -(defalias '-any '-some) -(defalias '--any '--some) - -(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? (val) - (declare (pure t) (side-effect-free t)) - (not (null val))) - -(defmacro --any? (form list) - "Anaphoric form of `-any?'." - (declare (debug (form form))) - `(---truthy? (--some ,form ,list))) - -(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) - "Anaphoric form of `-all?'." - (declare (debug (form form))) - (let ((a (make-symbol "all"))) - `(let ((,a t)) - (--each-while ,list ,a (setq ,a ,form)) - (---truthy? ,a)))) - -(defun -all? (pred list) - "Return t if (PRED x) is non-nil for all x in LIST, else nil. - -Alias: `-all-p', `-every?', `-every-p'" - (--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))) - -(defun -take (n list) - "Return a new list of the first N items in LIST, or all items if there are fewer than N. - -See also: `-take-last'" - (declare (pure t) (side-effect-free t)) - (let (result) - (--dotimes n - (when list - (!cons (car list) result) - (!cdr list))) - (nreverse result))) - -(defun -take-last (n list) - "Return the last N items of LIST in order. - -See also: `-take'" - (declare (pure t) (side-effect-free t)) - (copy-sequence (last list n))) - -(defalias '-drop 'nthcdr - "Return the tail of LIST without the first N items. - -See also: `-drop-last' - -\(fn N LIST)") - -(defun -drop-last (n list) - "Remove the last N items of LIST and return a copy. - -See also: `-drop'" - ;; No alias because we don't want magic optional argument - (declare (pure t) (side-effect-free t)) - (butlast list n)) - -(defmacro --take-while (form list) - "Anaphoric form of `-take-while'." - (declare (debug (form form))) - (let ((r (make-symbol "result"))) - `(let (,r) - (--each-while ,list ,form (!cons it ,r)) - (nreverse ,r)))) - -(defun -take-while (pred list) - "Return a new list of successive items from LIST while (PRED item) returns a non-nil value." - (--take-while (funcall pred it) list)) - -(defmacro --drop-while (form list) - "Anaphoric form of `-drop-while'." - (declare (debug (form form))) - (let ((l (make-symbol "list"))) - `(let ((,l ,list)) - (while (and ,l (let ((it (car ,l))) ,form)) - (!cdr ,l)) - ,l))) - -(defun -drop-while (pred list) - "Return the tail of LIST starting from the first item for which (PRED item) returns nil." - (--drop-while (funcall pred it) list)) - -(defun -split-at (n list) - "Return a list of ((-take N LIST) (-drop N LIST)), in no more than one pass through the list." - (declare (pure t) (side-effect-free t)) - (let (result) - (--dotimes n - (when list - (!cons (car list) result) - (!cdr list))) - (list (nreverse result) list))) - -(defun -rotate (n list) - "Rotate LIST N places to the right. With N negative, rotate to the left. -The time complexity is O(n)." - (declare (pure t) (side-effect-free t)) - (when list - (let* ((len (length list)) - (n-mod-len (mod n len)) - (new-tail-len (- len n-mod-len))) - (append (-drop 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 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 (form form))) - `(-split-when (lambda (it) (equal it ,item)) ,list)) - -(defmacro --split-when (form list) - "Anaphoric version of `-split-when'." - (declare (debug (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 ---partition-all-in-steps-reversed (n step list) - "Private: Used by -partition-all-in-steps and -partition-in-steps." - (when (< step 1) - (error "Step must be a positive number, or you're looking at some juicy infinite loops.")) - (let ((result nil)) - (while list - (!cons (-take n list) result) - (setq list (-drop 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 (---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 (---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)) - -(defun -partition-after-pred (pred list) - "Partition directly after each time PRED is true on an element of LIST." - (when list - (let ((rest (-partition-after-pred pred - (cdr list)))) - (if (funcall pred (car list)) - ;;split after (car list) - (cons (list (car list)) - rest) - - ;;don't split after (car list) - (cons (cons (car list) - (car rest)) - (cdr rest)))))) - -(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 copy of LIST that will cycle through the -elements and repeat from the beginning." - (declare (pure t) (side-effect-free t)) - (let ((newlist (-map 'identity 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 (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 -partial (fn &rest args) - "Take a function FN and fewer than the normal arguments to FN, -and return a fn that takes a variable number of additional ARGS. -When called, the returned function calls FN with ARGS first and -then additional args." - (apply 'apply-partially fn args)) - -(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 (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 (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'." - `(-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--> (x &optional form &rest more) - "When expr in 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)))) - -(defun -grade-up (comparator list) - "Grade elements of LIST using COMPARATOR relation, yielding a -permutation vector such that applying this permutation to LIST -sorts it in ascending order." - ;; ugly hack to "fix" lack of lexical scope - (let ((comp `(lambda (it other) (funcall ',comparator (car it) (car other))))) - (->> (--map-indexed (cons it it-index) list) - (-sort comp) - (-map 'cdr)))) - -(defun -grade-down (comparator list) - "Grade elements of LIST using COMPARATOR relation, yielding a -permutation vector such that applying this permutation to LIST -sorts it in descending order." - ;; ugly hack to "fix" lack of lexical scope - (let ((comp `(lambda (it other) (funcall ',comparator (car other) (car it))))) - (->> (--map-indexed (cons it it-index) list) - (-sort comp) - (-map '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--vector-tail (seq start) - "Return the tail of SEQ starting at START." - (cond - ((vectorp seq) - (let* ((re-length (- (length seq) start)) - (re (make-vector re-length 0))) - (--dotimes re-length (aset re it (aref seq (+ it start)))) - re)) - ((stringp seq) - (substring seq start)))) - -(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)) - `(dash--vector-tail ,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 (dash--vector-tail 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 the description of destructuring mechanism." - (declare (doc-string 2) (indent defun) - (debug (&define sexp - [&optional stringp] - [&optional ("interactive" interactive)] - def-body))) - (cond - ((not (consp match-form)) - (signal 'wrong-type-argument "match-form must be a list")) - ;; no destructuring, so just return regular lambda to make things faster - ((-all? 'symbolp match-form) - `(lambda ,match-form ,@body)) - (t - (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 to create the extra bindings to ensure that. - ;; We should find a way to optimize that. Not critical however. - `(lambda ,(--map (cadr it) 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) - (error "Odd number of arguments")) - (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 prefix of LIST. - -Alias: `-is-prefix-p'" - (declare (pure t) (side-effect-free t)) - (--each-while list (equal (car prefix) it) - (!cdr prefix)) - (not prefix)) - -(defun -is-suffix? (suffix list) - "Return non-nil if SUFFIX is suffix of LIST. - -Alias: `-is-suffix-p'" - (declare (pure t) (side-effect-free t)) - (-is-prefix? (reverse suffix) (reverse list))) - -(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 (form form))) - `(-sort (lambda (it other) ,form) ,list)) - -(defun -list (&rest args) - "Return a list with ARGS. - -If first item of ARGS is already a list, simply return ARGS. If -not, return a list with ARGS as elements." - (declare (pure t) (side-effect-free t)) - (let ((arg (car args))) - (if (listp arg) arg args))) - -(defun -repeat (n x) - "Return a list with X repeated N times. -Return nil if N is less than 1." - (declare (pure t) (side-effect-free t)) - (let (ret) - (--dotimes n (!cons x ret)) - ret)) - -(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)) - (unless (consp list) - (error "LIST must be non-empty")) - (-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)) - (unless (consp list) - (error "LIST must be non-empty")) - (-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 (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 (form form))) - `(-min-by (lambda (it other) ,form) ,list)) - -(defun -iterate (fun init n) - "Return a list of iterated applications of FUN to INIT. - -This means a list of form: - - (init (fun init) (fun (fun init)) ...) - -N is the length of the returned list." - (if (= n 0) nil - (let ((r (list init))) - (--dotimes (1- n) - (push (funcall fun (car r)) r)) - (nreverse r)))) - -(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'." - `(-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 (form form))) - `(-unfold (lambda (it) ,form) ,seed)) - -(defun -cons-pair? (con) - "Return non-nil if CON is true cons pair. -That is (A . B) where B is not a list. - -Alias: `-cons-pair-p'" - (declare (pure t) (side-effect-free t)) - (and (listp con) - (not (listp (cdr con))))) - -(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 (form 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 (form 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 (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 (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 (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'." - `(-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'." - `(-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)) - -(defun dash-enable-font-lock () - "Add syntax highlighting to dash functions, macros and magic values." - (eval-after-load 'lisp-mode - '(progn - (let ((new-keywords '( - "!cons" - "!cdr" - "-each" - "--each" - "-each-indexed" - "--each-indexed" - "-each-while" - "--each-while" - "-doto" - "-dotimes" - "--dotimes" - "-map" - "--map" - "-reduce-from" - "--reduce-from" - "-reduce" - "--reduce" - "-reduce-r-from" - "--reduce-r-from" - "-reduce-r" - "--reduce-r" - "-reductions-from" - "-reductions-r-from" - "-reductions" - "-reductions-r" - "-filter" - "--filter" - "-select" - "--select" - "-remove" - "--remove" - "-reject" - "--reject" - "-remove-first" - "--remove-first" - "-reject-first" - "--reject-first" - "-remove-last" - "--remove-last" - "-reject-last" - "--reject-last" - "-remove-item" - "-non-nil" - "-keep" - "--keep" - "-map-indexed" - "--map-indexed" - "-splice" - "--splice" - "-splice-list" - "--splice-list" - "-map-when" - "--map-when" - "-replace-where" - "--replace-where" - "-map-first" - "--map-first" - "-map-last" - "--map-last" - "-replace" - "-replace-first" - "-replace-last" - "-flatten" - "-flatten-n" - "-concat" - "-mapcat" - "--mapcat" - "-copy" - "-cons*" - "-snoc" - "-first" - "--first" - "-find" - "--find" - "-some" - "--some" - "-any" - "--any" - "-last" - "--last" - "-first-item" - "-second-item" - "-third-item" - "-fourth-item" - "-fifth-item" - "-last-item" - "-butlast" - "-count" - "--count" - "-any?" - "--any?" - "-some?" - "--some?" - "-any-p" - "--any-p" - "-some-p" - "--some-p" - "-some->" - "-some->>" - "-some-->" - "-all?" - "-all-p" - "--all?" - "--all-p" - "-every?" - "--every?" - "-all-p" - "--all-p" - "-every-p" - "--every-p" - "-none?" - "--none?" - "-none-p" - "--none-p" - "-only-some?" - "--only-some?" - "-only-some-p" - "--only-some-p" - "-slice" - "-take" - "-drop" - "-drop-last" - "-take-last" - "-take-while" - "--take-while" - "-drop-while" - "--drop-while" - "-split-at" - "-rotate" - "-insert-at" - "-replace-at" - "-update-at" - "--update-at" - "-remove-at" - "-remove-at-indices" - "-split-with" - "--split-with" - "-split-on" - "-split-when" - "--split-when" - "-separate" - "--separate" - "-partition-all-in-steps" - "-partition-in-steps" - "-partition-all" - "-partition" - "-partition-after-item" - "-partition-after-pred" - "-partition-before-item" - "-partition-before-pred" - "-partition-by" - "--partition-by" - "-partition-by-header" - "--partition-by-header" - "-group-by" - "--group-by" - "-interpose" - "-interleave" - "-unzip" - "-zip-with" - "--zip-with" - "-zip" - "-zip-fill" - "-zip-lists" - "-zip-pair" - "-cycle" - "-pad" - "-annotate" - "--annotate" - "-table" - "-table-flat" - "-partial" - "-elem-index" - "-elem-indices" - "-find-indices" - "--find-indices" - "-find-index" - "--find-index" - "-find-last-index" - "--find-last-index" - "-select-by-indices" - "-select-columns" - "-select-column" - "-grade-up" - "-grade-down" - "->" - "->>" - "-->" - "-as->" - "-when-let" - "-when-let*" - "--when-let" - "-if-let" - "-if-let*" - "--if-let" - "-let*" - "-let" - "-lambda" - "-distinct" - "-uniq" - "-union" - "-intersection" - "-difference" - "-powerset" - "-permutations" - "-inits" - "-tails" - "-common-prefix" - "-common-suffix" - "-contains?" - "-contains-p" - "-same-items?" - "-same-items-p" - "-is-prefix-p" - "-is-prefix?" - "-is-suffix-p" - "-is-suffix?" - "-is-infix-p" - "-is-infix?" - "-sort" - "--sort" - "-list" - "-repeat" - "-sum" - "-running-sum" - "-product" - "-running-product" - "-max" - "-min" - "-max-by" - "--max-by" - "-min-by" - "--min-by" - "-iterate" - "--iterate" - "-fix" - "--fix" - "-unfold" - "--unfold" - "-cons-pair?" - "-cons-pair-p" - "-cons-to-list" - "-value-to-list" - "-tree-mapreduce-from" - "--tree-mapreduce-from" - "-tree-mapreduce" - "--tree-mapreduce" - "-tree-map" - "--tree-map" - "-tree-reduce-from" - "--tree-reduce-from" - "-tree-reduce" - "--tree-reduce" - "-tree-seq" - "--tree-seq" - "-tree-map-nodes" - "--tree-map-nodes" - "-clone" - "-rpartial" - "-juxt" - "-applify" - "-on" - "-flip" - "-const" - "-cut" - "-orfn" - "-andfn" - "-iteratefn" - "-fixfn" - "-prodfn" - )) - (special-variables '( - "it" - "it-index" - "acc" - "other" - ))) - (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "\\_<" (regexp-opt special-variables 'paren) "\\_>") - 1 font-lock-variable-name-face)) 'append) - (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "(\\s-*" (regexp-opt new-keywords 'paren) "\\_>") - 1 font-lock-keyword-face)) 'append)) - (--each (buffer-list) - (with-current-buffer it - (when (and (eq major-mode 'emacs-lisp-mode) - (boundp 'font-lock-mode) - font-lock-mode) - (font-lock-refresh-defaults))))))) - -(provide 'dash) -;;; dash.el ends here diff --git a/elpa/dash-20200524.1947/dash.info b/elpa/dash-20200524.1947/dash.info deleted file mode 100644 index a88cea7..0000000 --- a/elpa/dash-20200524.1947/dash.info +++ /dev/null @@ -1,3410 +0,0 @@ -This is dash.info, produced by makeinfo version 6.5 from dash.texi. - -This manual is for ‘dash.el’ version 2.12.1. - - Copyright © 2012-2015 Magnar Sveen - - 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 - <http://www.gnu.org/licenses/>. -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.el’ version 2.12.1. - - Copyright © 2012-2015 Magnar Sveen - - 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 - <http://www.gnu.org/licenses/>. - -* Menu: - -* Installation:: -* Functions:: -* Development:: -* Index:: - -— The Detailed Node Listing — - -Installation - -* Using in a package:: -* Syntax highlighting of dash functions:: - -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 -* Changes:: List of significant changes by version -* Contributors:: List of contributors - - -File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top - -1 Installation -************** - -It’s available on Melpa (https://melpa.org/); use ‘M-x package-install’: - -‘M-x package-install <RET> dash’ - Install the dash library. - -‘M-x package-install <RET> dash-functional’ - Optional, if you want the function combinators. - - Alternatively, you can just dump dash.el or dash-functional.el in -your load path somewhere. - -* Menu: - -* Using in a package:: -* Syntax highlighting of dash functions:: - - -File: dash.info, Node: Using in a package, Next: Syntax highlighting of dash functions, Up: Installation - -1.1 Using in a package -====================== - -Add this to the big comment block at the top: - - ;; Package-Requires: ((dash "2.12.1")) - -To get function combinators: - - ;; Package-Requires: ((dash "2.12.1") (dash-functional "1.2.0") (emacs "24")) - - -File: dash.info, Node: Syntax highlighting of dash functions, Prev: Using in a package, Up: Installation - -1.2 Syntax highlighting of dash functions -========================================= - -Font lock of dash functions in emacs lisp buffers is now optional. -Include this in your emacs settings to get syntax highlighting: - - (eval-after-load 'dash '(dash-enable-font-lock)) - - -File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top - -2 Functions -*********** - -This chapter contains reference documentation for the dash application -programming interface (API). All functions and constructs in the library -are prefixed with a dash (-). - - There are also anaphoric versions of functions where that makes -sense, prefixed with two dashes instead of one. - - For instance, while ‘-map’ takes a function to map over the list, one -can also use the anaphoric form with double dashes - which will then be -executed with ‘it’ exposed as the list item. Here’s an example: - - (-map (lambda (n) (* n n)) '(1 2 3 4)) ;; normal version - - (--map (* it it) '(1 2 3 4)) ;; anaphoric version - -Of course, the original can also be written like - - (defun square (n) (* n n)) - - (-map 'square '(1 2 3 4)) - -which demonstrates the usefulness of both versions. - -* 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 new list. - - -- Function: -map (fn list) - Return a new list consisting of the result of applying FN to the - items in LIST. - - (-map (lambda (num) (* num num)) '(1 2 3 4)) - ⇒ '(1 4 9 16) - (-map 'square '(1 2 3 4)) - ⇒ '(1 4 9 16) - (--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) - Return a new list consisting of the result of (FN index item) for - each item in LIST. - - In the anaphoric form ‘--map-indexed’, the index is exposed as - symbol ‘it-index’. - - 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) - - -- 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 (arg) - Create a shallow copy of LIST. - - (fn 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 a - non-nil value. - - Alias: ‘-select’ - - See also: ‘-keep’ (*note -keep::), ‘-remove’ (*note -remove::). - - (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) - ⇒ '(2 4) - (-filter 'even? '(1 2 3 4)) - ⇒ '(2 4) - (--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’ - - See also: ‘-filter’ (*note -filter::). - - (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) - ⇒ '(1 3) - (-remove 'even? '(1 2 3 4)) - ⇒ '(1 3) - (--remove (= 0 (% it 2)) '(1 2 3 4)) - ⇒ '(1 3) - - -- Function: -remove-first (pred list) - Return a new list with the first item matching PRED removed. - - Alias: ‘-reject-first’ - - See also: ‘-remove’ (*note -remove::), ‘-map-first’ (*note - -map-first::) - - (-remove-first 'even? '(1 3 5 4 7 8 10)) - ⇒ '(1 3 5 7 8 10) - (-remove-first 'stringp '(1 2 "first" "second" "third")) - ⇒ '(1 2 "second" "third") - (--remove-first (> it 3) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 2 3 5 6 7 8 9 10) - - -- Function: -remove-last (pred list) - Return a new list with the last item matching PRED removed. - - Alias: ‘-reject-last’ - - See also: ‘-remove’ (*note -remove::), ‘-map-last’ (*note - -map-last::) - - (-remove-last 'even? '(1 3 5 4 7 8 10 11)) - ⇒ '(1 3 5 4 7 8 11) - (-remove-last 'stringp '(1 2 "last" "second" "third")) - ⇒ '(1 2 "last" "second") - (--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) - Remove all occurrences of ITEM from LIST. - - 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" "dave")) - ⇒ '("alice" "eve" "dave") - - -- Function: -non-nil (list) - Return all non-nil elements of LIST. - - (-non-nil '(1 nil 2 nil nil 3 4 nil 5 nil)) - ⇒ '(1 2 3 4 5) - - -- 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 new list of the first N items in LIST, or all items if - there are fewer than N. - - 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) - - -- Function: -take-last (n list) - Return the last N items of LIST in order. - - 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 of LIST without the first N items. - - See also: ‘-drop-last’ (*note -drop-last::) - - (fn N LIST) - - (-drop 3 '(1 2 3 4 5)) - ⇒ '(4 5) - (-drop 17 '(1 2 3 4 5)) - ⇒ '() - - -- Function: -drop-last (n list) - Remove the last N items of LIST and return a copy. - - See also: ‘-drop’ (*note -drop::) - - (-drop-last 3 '(1 2 3 4 5)) - ⇒ '(1 2) - (-drop-last 17 '(1 2 3 4 5)) - ⇒ '() - - -- Function: -take-while (pred list) - Return a new list of successive items from LIST while (PRED item) - returns a non-nil value. - - (-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) - Return the tail of LIST starting from the first item for which - (PRED item) returns nil. - - (-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 the - items in LIST. - - If you want to select the original items satisfying a predicate use - ‘-filter’ (*note -filter::). - - (-keep 'cdr '((1 2 3) (4 5) (6))) - ⇒ '((2 3) (5)) - (-keep (lambda (num) (when (> num 3) (* 10 num))) '(1 2 3 4 5 6)) - ⇒ '(40 50 60) - (--keep (when (> 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 into single value. - - -- Function: -reduce-from (fn initial-value list) - Return the result of applying FN to INITIAL-VALUE and the first - item in LIST, then applying FN to that result and the 2nd item, - etc. If LIST contains no items, return INITIAL-VALUE and do not - call FN. - - In the anaphoric form ‘--reduce-from’, the accumulated value is - exposed as symbol ‘acc’. - - See also: ‘-reduce’ (*note -reduce::), ‘-reduce-r’ (*note - -reduce-r::) - - (-reduce-from '- 10 '(1 2 3)) - ⇒ 4 - (-reduce-from (lambda (memo item) (format "(%s - %d)" memo item)) "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 initial-value list) - Replace conses with FN, nil with INITIAL-VALUE and evaluate the - resulting expression. If LIST is empty, INITIAL-VALUE is returned - and FN is not called. - - Note: this function works the same as ‘-reduce-from’ (*note - -reduce-from::) but the operation associates from right instead of - from left. - - See also: ‘-reduce-r’ (*note -reduce-r::), ‘-reduce’ (*note - -reduce::) - - (-reduce-r-from '- 10 '(1 2 3)) - ⇒ -8 - (-reduce-r-from (lambda (item memo) (format "(%d - %s)" item memo)) "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) - Return the result of applying FN to the first 2 items in LIST, then - applying FN to that result and the 3rd item, etc. If LIST contains - no items, return the result of calling FN with no arguments. If - LIST contains a single item, return that item and do not call FN. - - In the anaphoric form ‘--reduce’, the accumulated value is exposed - as symbol ‘acc’. - - See also: ‘-reduce-from’ (*note -reduce-from::), ‘-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) - Replace conses with FN and evaluate the resulting expression. The - final nil is ignored. If LIST contains no items, return the result - of calling FN with no arguments. If LIST contains a single item, - return that item and do not call FN. - - The first argument of FN is the new item, the second is the - accumulated value. - - Note: this function works the same as ‘-reduce’ (*note -reduce::) - but the operation associates from right instead of from left. - - See also: ‘-reduce-r-from’ (*note -reduce-r-from::), ‘-reduce’ - (*note -reduce::) - - (-reduce-r '- '(1 2 3 4)) - ⇒ -2 - (-reduce-r (lambda (item memo) (format "%s-%d" memo item)) '(1 2 3)) - ⇒ "3-2-1" - (--reduce-r (format "%s-%d" acc it) '(1 2 3)) - ⇒ "3-2-1" - - -- Function: -reductions-from (fn init list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce-from’ (*note -reduce-from::) for explanation of the - arguments. - - See also: ‘-reductions’ (*note -reductions::), ‘-reductions-r’ - (*note -reductions-r::), ‘-reduce-r’ (*note -reduce-r::) - - (-reductions-from (lambda (a i) (format "(%s FN %d)" a i)) "INIT" '(1 2 3 4)) - ⇒ '("INIT" "(INIT FN 1)" "((INIT FN 1) FN 2)" "(((INIT FN 1) FN 2) FN 3)" "((((INIT FN 1) FN 2) FN 3) FN 4)") - (-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) - - -- Function: -reductions-r-from (fn init list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce-r-from’ (*note -reduce-r-from::) for explanation of - the arguments. - - See also: ‘-reductions-r’ (*note -reductions-r::), ‘-reductions’ - (*note -reductions::), ‘-reduce’ (*note -reduce::) - - (-reductions-r-from (lambda (i a) (format "(%d FN %s)" i a)) "INIT" '(1 2 3 4)) - ⇒ '("(1 FN (2 FN (3 FN (4 FN INIT))))" "(2 FN (3 FN (4 FN INIT)))" "(3 FN (4 FN INIT))" "(4 FN INIT)" "INIT") - (-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) - - -- Function: -reductions (fn list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce’ (*note -reduce::) for explanation of the arguments. - - See also: ‘-reductions-from’ (*note -reductions-from::), - ‘-reductions-r’ (*note -reductions-r::), ‘-reduce-r’ (*note - -reduce-r::) - - (-reductions (lambda (a i) (format "(%s FN %d)" a i)) '(1 2 3 4)) - ⇒ '(1 "(1 FN 2)" "((1 FN 2) FN 3)" "(((1 FN 2) FN 3) FN 4)") - (-reductions '+ '(1 2 3 4)) - ⇒ '(1 3 6 10) - (-reductions '* '(1 2 3 4)) - ⇒ '(1 2 6 24) - - -- Function: -reductions-r (fn list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce-r’ (*note -reduce-r::) for explanation of the - arguments. - - See also: ‘-reductions-r-from’ (*note -reductions-r-from::), - ‘-reductions’ (*note -reductions::), ‘-reduce’ (*note -reduce::) - - (-reductions-r (lambda (i a) (format "(%d FN %s)" i a)) '(1 2 3 4)) - ⇒ '("(1 FN (2 FN (3 FN 4)))" "(2 FN (3 FN 4))" "(3 FN 4)" 4) - (-reductions-r '+ '(1 2 3 4)) - ⇒ '(10 9 7 4) - (-reductions-r '* '(1 2 3 4)) - ⇒ '(24 24 12 4) - - -- 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 - - -- 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 - - -- 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)) - ⇒ nil - (-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)) - ⇒ nil - (-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 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 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 -============== - - -- 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? 'even? '(1 2 3)) - ⇒ t - (-any? 'even? '(1 3 5)) - ⇒ 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. - - Alias: ‘-all-p’, ‘-every?’, ‘-every-p’ - - (-all? 'even? '(1 2 3)) - ⇒ nil - (-all? 'even? '(2 4 6)) - ⇒ t - (--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 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 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 - - -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) - Return a list of ((-take N LIST) (-drop N LIST)), in no more than - one pass through the list. - - (-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) - - -- 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 directly after each time PRED is true on an element of - LIST. - - (-partition-after-pred #'odd? '()) - ⇒ '() - (-partition-after-pred #'odd? '(1)) - ⇒ '((1)) - (-partition-after-pred #'odd? '(0 1)) - ⇒ '((0 1)) - - -- Function: -partition-before-pred (pred list) - Partition directly before each time PRED is true on an element of - LIST. - - (-partition-before-pred #'odd? '()) - ⇒ '() - (-partition-before-pred #'odd? '(1)) - ⇒ '((1)) - (-partition-before-pred #'odd? '(0 1)) - ⇒ '((0) (1)) - - -- 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 -============ - -Return indices of elements based on predicates, sort elements by indices -etc. - - -- 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, yielding 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, yielding 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. With N negative, rotate to the - left. 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 list with X repeated N times. 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 members of ARGS are used as the final cons of the result - so if the final member of ARGS is not a list the result is a dotted - list. - - (-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: -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 copy of LIST that will cycle through the - elements and repeat 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 x in LIST where (PRED x) is non-nil, else nil. - - To get the first item in the list no questions asked, use ‘car’. - - Alias: ‘-find’ - - (-first 'even? '(1 2 3)) - ⇒ 2 - (-first 'even? '(1 3 5)) - ⇒ nil - (-first 'null '(1 3 5)) - ⇒ nil - - -- Function: -some (pred list) - Return (PRED x) for the first LIST item where (PRED x) is non-nil, - else nil. - - Alias: ‘-any’ - - (-some 'even? '(1 2 3)) - ⇒ t - (-some 'null '(1 2 3)) - ⇒ nil - (-some 'null '(1 2 nil)) - ⇒ t - - -- 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::). - - (fn LIST) - - (-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 (arg1) - Return the second item of LIST, or nil if LIST is too short. - - See also: ‘-third-item’ (*note -third-item::). - - (fn LIST) - - (-second-item '(1 2 3)) - ⇒ 2 - (-second-item nil) - ⇒ nil - - -- Function: -third-item (arg1) - Return the third item of LIST, or nil if LIST is too short. - - See also: ‘-fourth-item’ (*note -fourth-item::). - - (fn LIST) - - (-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 (&rest args) - Return a list with ARGS. - - If first item of ARGS is already a list, simply return ARGS. If - not, return a list with ARGS as elements. - - (-list 1) - ⇒ '(1) - (-list 1 2 3) - ⇒ '(1 2 3) - (-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 4 5 6))) - ⇒ '((1) (2) (3) (4) (5) (6)) - (let ((data '(("starwars" "scifi") ("jedi" "starwars" "warrior")))) (--fix (-uniq (--mapcat (cons it (cdr (assoc it data))) 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) "}" '((elips-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam))))) - ⇒ "{elips-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 -===================== - - -- 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--> (x &optional form &rest more) - When expr in non-nil, thread it through the first form (via ‘-->’ - (*note -->::)), and when that result is non-nil, through the next - form, etc. - - (-some--> "def" (concat "abc" it "ghi")) - ⇒ "abcdefghi" - (-some--> nil (concat "abc" it "ghi")) - ⇒ nil - (-some--> '(1 3 5) (-filter 'even? it) (append it it) (-map 'square it)) - ⇒ nil - - -File: dash.info, Node: Binding, Next: Side-effects, Prev: Threading macros, Up: Functions - -2.13 Binding -============ - -Convenient versions of ‘let‘ and ‘let*‘ constructs combined with 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::). - - (fn (VAR VAL) &rest BODY) - - (-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::). - - (fn (VAR VAL) THEN &rest ELSE) - - (-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 the description of 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 (&rest forms) - 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. - - (fn [MATCH-FORM VAL]...) - - (progn (-setq a 1) a) - ⇒ 1 - (progn (-setq (a b) (list 1 2)) (list a b)) - ⇒ '(1 2) - (progn (-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 with every item in LIST. Return nil, used for side-effects - only. - - (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s))))) - ⇒ nil - (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s)))) s) - ⇒ '(3 2 1) - (let (s) (--each '(1 2 3) (setq s (cons it s))) s) - ⇒ '(3 2 1) - - -- Function: -each-while (list pred fn) - Call FN with every item in LIST while (PRED item) is non-nil. - Return nil, used for side-effects only. - - (let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) - ⇒ '(4 2) - (let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) - ⇒ '(2 1) - - -- Function: -each-indexed (list fn) - Call (FN index item) for each item in LIST. - - In the anaphoric form ‘--each-indexed’, the index is exposed as - symbol ‘it-index’. - - See also: ‘-map-indexed’ (*note -map-indexed::). - - (let (s) (-each-indexed '(a b c) (lambda (index item) (setq s (cons (list item index) s)))) s) - ⇒ '((c 2) (b 1) (a 0)) - (let (s) (--each-indexed '(a b c) (setq s (cons (list it it-index) s))) s) - ⇒ '((c 2) (b 1) (a 0)) - - -- Function: -each-r (list fn) - Call FN with every item in LIST in reversed order. Return nil, - used for side-effects only. - - (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s))))) - ⇒ nil - (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s)))) s) - ⇒ '(1 2 3) - (let (s) (--each-r '(1 2 3) (setq s (cons it s))) s) - ⇒ '(1 2 3) - - -- Function: -each-r-while (list pred fn) - Call FN with every item in reversed LIST while (PRED item) is - non-nil. Return nil, used for side-effects only. - - (let (s) (-each-r-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) - ⇒ '(6) - (let (s) (--each-r-while '(1 2 3 4) (>= it 3) (!cons it s)) s) - ⇒ '(3 4) - - -- Function: -dotimes (num fn) - Repeatedly calls FN (presumably for side-effects) passing in - integers from 0 through NUM-1. - - (let (s) (-dotimes 3 (lambda (n) (!cons n s))) s) - ⇒ '(2 1 0) - (let (s) (--dotimes 5 (!cons it s)) s) - ⇒ '(4 3 2 1 0) - - -- Macro: -doto (eval-initial-value &rest forms) - Eval a form, then insert that form as the 2nd argument to other - forms. The EVAL-INITIAL-VALUE form is evaluated once. Its result - is passed to FORMS, which are then evaluated sequentially. Returns - the target form. - - (-doto '(1 2 3) (!cdr) (!cdr)) - ⇒ '(3) - (-doto '(1 . 2) (setcar 3) (setcdr 4)) - ⇒ '(3 . 4) - - -- Macro: --doto (eval-initial-value &rest forms) - Anaphoric form of ‘-doto’ (*note -doto::). Note: ‘it’ is not - required in each form. - - (gethash "key" (--doto (make-hash-table :test 'equal) (puthash "key" "value" it))) - ⇒ "value" - - -File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side-effects, Up: Functions - -2.15 Destructive operations -=========================== - - -- 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 -========================= - -These combinators require Emacs 24 for its lexical scope. So they are -offered in a separate package: ‘dash-functional‘. - - -- Function: -partial (fn &rest args) - Takes a function FN and fewer than the normal arguments to FN, and - returns a fn that takes a variable number of additional ARGS. When - called, the returned function calls FN with ARGS first and then - additional args. - - (funcall (-partial '- 5) 3) - ⇒ 2 - (funcall (-partial '+ 5 2) 3) - ⇒ 10 - - -- Function: -rpartial (fn &rest args) - Takes a function FN and fewer than the normal arguments to FN, and - returns a fn that takes a variable number of additional ARGS. When - called, the returned function calls FN with the additional args - first and then ARGS. - - (funcall (-rpartial '- 5) 8) - ⇒ 3 - (funcall (-rpartial '- 5 2) 10) - ⇒ 3 - - -- Function: -juxt (&rest fns) - Takes a list of functions and returns a fn that is the - juxtaposition of those fns. The returned fn takes a variable - number of args, and returns a list containing the result of - applying each fn to the args (left-to-right). - - (funcall (-juxt '+ '-) 3 5) - ⇒ '(8 -2) - (-map (-juxt 'identity 'square) '(1 2 3)) - ⇒ '((1 1) (2 4) (3 9)) - - -- Function: -compose (&rest fns) - Takes a list of functions and returns a fn that is the composition - of those fns. The returned fn takes a variable number of - arguments, and returns the result of applying each fn to the result - of applying the previous fn to the arguments (right-to-left). - - (funcall (-compose 'square '+) 2 3) - ⇒ (square (+ 2 3)) - (funcall (-compose 'identity 'square) 3) - ⇒ (square 3) - (funcall (-compose 'square 'identity) 3) - ⇒ (square 3) - - -- Function: -applify (fn) - Changes an n-arity function FN to a 1-arity function that expects a - list with n items as arguments - - (-map (-applify '+) '((1 1 1) (1 2 3) (5 5 5))) - ⇒ '(3 6 15) - (-map (-applify (lambda (a b c) `(,a (,b (,c))))) '((1 1 1) (1 2 3) (5 5 5))) - ⇒ '((1 (1 (1))) (1 (2 (3))) (5 (5 (5)))) - (funcall (-applify '<) '(3 6)) - ⇒ t - - -- Function: -on (operator transformer) - Return a function of two arguments that first applies TRANSFORMER - to each of them and then applies OPERATOR on the results (in the - same order). - - In types: (b -> b -> c) -> (a -> b) -> a -> a -> c - - (-sort (-on '< 'length) '((1 2 3) (1) (1 2))) - ⇒ '((1) (1 2) (1 2 3)) - (-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) - ⇒ '(4) - (-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) - ⇒ 22 - - -- Function: -flip (func) - Swap the order of arguments for binary function FUNC. - - In types: (a -> b -> c) -> b -> a -> c - - (funcall (-flip '<) 2 1) - ⇒ t - (funcall (-flip '-) 3 8) - ⇒ 5 - (-sort (-flip '<) '(4 3 6 1)) - ⇒ '(6 4 3 1) - - -- 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 - (-map (-const 1) '("a" "b" "c" "d")) - ⇒ '(1 1 1 1) - (-sum (-map (-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 'list 'vector 'string)) - ⇒ '((1 2 3) [1 2 3] "") - - -- Function: -not (pred) - Take a unary predicate PRED and return a unary predicate that - returns t if PRED returns nil and nil if PRED returns non-nil. - - (funcall (-not 'even?) 5) - ⇒ t - (-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) - ⇒ '(1 2 3 4) - - -- Function: -orfn (&rest preds) - Take list of unary predicates PREDS and return a unary predicate - with argument x that returns non-nil if at least one of the PREDS - returns non-nil on x. - - In types: [a -> Bool] -> a -> Bool - - (-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 2 3 4 6 8 10) - (funcall (-orfn 'stringp 'even?) "foo") - ⇒ t - - -- Function: -andfn (&rest preds) - Take list of unary predicates PREDS and return a unary predicate - with argument x that returns non-nil if all of the PREDS returns - non-nil on x. - - In types: [a -> Bool] -> a -> Bool - - (funcall (-andfn (-cut < <> 10) 'even?) 6) - ⇒ t - (funcall (-andfn (-cut < <> 10) 'even?) 12) - ⇒ nil - (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 3 5) - - -- 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-equal) 0.7) - ⇒ 0.7390851332151607 - (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) - ⇒ 1.8555845286409378 - (funcall (-fixfn 'sin 'approx-equal) 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: Index, Prev: Functions, Up: Top - -3 Development -************* - -The dash repository is hosted on GitHub: -<https://github.com/magnars/dash.el> - -* Menu: - -* Contribute:: How to contribute -* Changes:: List of significant changes by version -* Contributors:: List of contributors - - -File: dash.info, Node: Contribute, Next: Changes, Up: Development - -3.1 Contribute -============== - -Yes, please do. Pure functions in the list manipulation realm only, -please. There’s a suite of tests in dev/examples.el, so remember to add -tests for your function, or it might get broken later. - - Run the tests with ‘./run-tests.sh’. Create the docs with -‘./create-docs.sh’. I highly recommend that you install these as a -pre-commit hook, so that the tests are always running and the docs are -always in sync: - -cp pre-commit.sh .git/hooks/pre-commit - - Oh, and don’t edit ‘README.md’ directly, it is auto-generated. -Change ‘readme-template.md’ or ‘examples-to-docs.el’ instead. The same -goes for the info manual. - - -File: dash.info, Node: Changes, Next: Contributors, Prev: Contribute, Up: Development - -3.2 Changes -=========== - -Changes in 2.10: - - • Add ‘-let’ destructuring to ‘-if-let’ and ‘-when-let’ (Fredrik - Bergroth) - -Changes in 2.9: - - • Add ‘-let’, ‘-let*’ and ‘-lambda’ with destructuring - • Add ‘-tree-seq’ and ‘-tree-map-nodes’ - • Add ‘-non-nil’ - • Add ‘-fix’ - • Add ‘-fixfn’ (dash-functional 1.2) - • Add ‘-copy’ (Wilfred Hughes) - -Changes in 2.8: - - • Add ‘-butlast’ - -Changes in 2.7: - - • ‘-zip’ now supports more than two lists (Steve Lamb) - • Add ‘-cycle’, ‘-pad’, ‘-annotate’, ‘-zip-fill’ (Steve Lamb) - • Add ‘-table’, ‘-table-flat’ (finite cartesian product) - • Add ‘-flatten-n’ - • ‘-slice’ now supports "step" argument - • Add functional combinators ‘-iteratefn’, ‘-prodfn’ - • Add ‘-replace’, ‘-splice’, ‘-splice-list’ which generalize - ‘-replace-at’ and ‘-insert-at’ - • Add ‘-compose’, ‘-iteratefn’ and ‘-prodfn’ (dash-functional 1.1) - -Changes in 2.6: - - • Add ‘-is-prefix-p’, ‘-is-suffix-p’, ‘-is-infix-p’ (Matus Goljer) - • Add ‘-iterate’, ‘-unfold’ (Matus Goljer) - • Add ‘-split-on’, ‘-split-when’ (Matus Goljer) - • Add ‘-find-last-index’ (Matus Goljer) - • Add ‘-list’ (Johan Andersson) - -Changes in 2.5: - - • Add ‘-same-items?’ (Johan Andersson) - • A few bugfixes - -Changes in 2.4: - - • Add ‘-snoc’ (Matus Goljer) - • Add ‘-replace-at’, ‘-update-at’, ‘-remove-at’, and - ‘-remove-at-indices’ (Matus Goljer) - -Changes in 2.3: - - • Add tree operations (Matus Goljer) - • Make font-lock optional - -Changes in 2.2: - - • Add ‘-compose’ (Christina Whyte) - -Changes in 2.1: - - • Add indexing operations (Matus Goljer) - -Changes in 2.0: - - • Split out ‘dash-functional.el’ (Matus Goljer) - • Add ‘-andfn’, ‘-orfn’, ‘-not’, ‘-cut’, ‘-const’, ‘-flip’ and ‘-on’. - (Matus Goljer) - • Fix ‘-min’, ‘-max’, ‘-min-by’ and ‘-max-by’ (Matus Goljer) - -Changes in 1.8: - - • Add ‘-first-item’ and ‘-last-item’ (Wilfred Hughes) - -Changes in 1.7: - - • Add ‘-rotate’ (Matus Goljer) - -Changes in 1.6: - - • Add ‘-min’, ‘-max’, ‘-min-by’ and ‘-max-by’ (Johan Andersson) - -Changes in 1.5: - - • Add ‘-sum’ and ‘-product’ (Johan Andersson) - -Changes in 1.4: - - • Add ‘-sort’ - • Add ‘-reduce-r’ (Matus Goljer) - • Add ‘-reduce-r-from’ (Matus Goljer) - -Changes in 1.3: - - • Add ‘-partition-in-steps’ - • Add ‘-partition-all-in-steps’ - -Changes in 1.2: - - • Add ‘-last’ (Matus Goljer) - • Add ‘-insert-at’ (Emanuel Evans) - • Add ‘-when-let’ and ‘-if-let’ (Emanuel Evans) - • Add ‘-when-let*’ and ‘-if-let*’ (Emanuel Evans) - • Some bugfixes - - -File: dash.info, Node: Contributors, Prev: Changes, Up: Development - -3.3 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 an n-ary version of ‘-zip’. - • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’ - family use ‘-let’ destructuring and improved script for generating - documentation. - • Mark Oteiza (https://github.com/holomorph) contributed 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. - - Thanks! - - -File: dash.info, Node: Index, Prev: Development, Up: Top - -Index -***** - - -* Menu: - -* !cdr: Destructive operations. - (line 14) -* !cons: Destructive operations. - (line 6) -* -->: Threading macros. (line 32) -* --doto: Side-effects. (line 81) -* ->: Threading macros. (line 6) -* ->>: Threading macros. (line 19) -* -all?: Predicates. (line 18) -* -andfn: Function combinators. - (line 138) -* -annotate: Maps. (line 79) -* -any?: Predicates. (line 6) -* -applify: Function combinators. - (line 55) -* -as->: Threading macros. (line 46) -* -butlast: Other list operations. - (line 340) -* -clone: Tree operations. (line 122) -* -common-prefix: Reductions. (line 223) -* -common-suffix: Reductions. (line 233) -* -compose: Function combinators. - (line 42) -* -concat: List to list. (line 22) -* -cons*: Other list operations. - (line 30) -* -const: Function combinators. - (line 92) -* -contains?: Predicates. (line 57) -* -copy: Maps. (line 134) -* -count: Reductions. (line 151) -* -cut: Function combinators. - (line 104) -* -cycle: Other list operations. - (line 168) -* -difference: Set operations. (line 20) -* -distinct: Set operations. (line 62) -* -dotimes: Side-effects. (line 61) -* -doto: Side-effects. (line 70) -* -drop: Sublist selection. (line 124) -* -drop-last: Sublist selection. (line 136) -* -drop-while: Sublist selection. (line 157) -* -each: Side-effects. (line 8) -* -each-indexed: Side-effects. (line 28) -* -each-r: Side-effects. (line 41) -* -each-r-while: Side-effects. (line 52) -* -each-while: Side-effects. (line 19) -* -elem-index: Indexing. (line 9) -* -elem-indices: Indexing. (line 21) -* -fifth-item: Other list operations. - (line 320) -* -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 234) -* -first-item: Other list operations. - (line 271) -* -fix: Other list operations. - (line 376) -* -fixfn: Function combinators. - (line 175) -* -flatten: List to list. (line 33) -* -flatten-n: List to list. (line 55) -* -flip: Function combinators. - (line 80) -* -fourth-item: Other list operations. - (line 310) -* -grade-down: Indexing. (line 81) -* -grade-up: Indexing. (line 71) -* -group-by: Partitioning. (line 187) -* -if-let: Binding. (line 36) -* -if-let*: Binding. (line 49) -* -inits: Reductions. (line 203) -* -insert-at: List to list. (line 109) -* -interleave: Other list operations. - (line 68) -* -interpose: Other list operations. - (line 58) -* -intersection: Set operations. (line 32) -* -is-infix?: Predicates. (line 110) -* -is-prefix?: Predicates. (line 86) -* -is-suffix?: Predicates. (line 98) -* -iterate: Unfolding. (line 9) -* -iteratefn: Function combinators. - (line 152) -* -juxt: Function combinators. - (line 31) -* -keep: List to list. (line 8) -* -lambda: Binding. (line 252) -* -last: Other list operations. - (line 261) -* -last-item: Other list operations. - (line 330) -* -let: Binding. (line 65) -* -let*: Binding. (line 232) -* -list: Other list operations. - (line 363) -* -map: Maps. (line 10) -* -map-first: Maps. (line 37) -* -map-indexed: Maps. (line 65) -* -map-last: Maps. (line 51) -* -map-when: Maps. (line 21) -* -mapcat: Maps. (line 123) -* -max: Reductions. (line 267) -* -max-by: Reductions. (line 277) -* -min: Reductions. (line 243) -* -min-by: Reductions. (line 253) -* -non-nil: Sublist selection. (line 79) -* -none?: Predicates. (line 30) -* -not: Function combinators. - (line 117) -* -on: Function combinators. - (line 66) -* -only-some?: Predicates. (line 42) -* -orfn: Function combinators. - (line 126) -* -pad: Other list operations. - (line 179) -* -partial: Function combinators. - (line 9) -* -partition: Partitioning. (line 74) -* -partition-after-item: Partitioning. (line 177) -* -partition-after-pred: Partitioning. (line 145) -* -partition-all: Partitioning. (line 86) -* -partition-all-in-steps: Partitioning. (line 109) -* -partition-before-item: Partitioning. (line 167) -* -partition-before-pred: Partitioning. (line 156) -* -partition-by: Partitioning. (line 121) -* -partition-by-header: Partitioning. (line 132) -* -partition-in-steps: Partitioning. (line 97) -* -permutations: Set operations. (line 52) -* -powerset: Set operations. (line 44) -* -prodfn: Function combinators. - (line 209) -* -product: Reductions. (line 181) -* -reduce: Reductions. (line 46) -* -reduce-from: Reductions. (line 8) -* -reduce-r: Reductions. (line 65) -* -reduce-r-from: Reductions. (line 27) -* -reductions: Reductions. (line 119) -* -reductions-from: Reductions. (line 87) -* -reductions-r: Reductions. (line 135) -* -reductions-r-from: Reductions. (line 103) -* -remove: Sublist selection. (line 23) -* -remove-at: List to list. (line 145) -* -remove-at-indices: List to list. (line 158) -* -remove-first: Sublist selection. (line 37) -* -remove-item: Sublist selection. (line 67) -* -remove-last: Sublist selection. (line 52) -* -repeat: Other list operations. - (line 19) -* -replace: List to list. (line 67) -* -replace-at: List to list. (line 120) -* -replace-first: List to list. (line 81) -* -replace-last: List to list. (line 95) -* -rotate: Other list operations. - (line 8) -* -rpartial: Function combinators. - (line 20) -* -running-product: Reductions. (line 191) -* -running-sum: Reductions. (line 169) -* -same-items?: Predicates. (line 72) -* -second-item: Other list operations. - (line 286) -* -select-by-indices: Sublist selection. (line 168) -* -select-column: Sublist selection. (line 198) -* -select-columns: Sublist selection. (line 179) -* -separate: Partitioning. (line 63) -* -setq: Binding. (line 274) -* -slice: Sublist selection. (line 85) -* -snoc: Other list operations. - (line 44) -* -some: Other list operations. - (line 248) -* -some-->: Threading macros. (line 83) -* -some->: Threading macros. (line 59) -* -some->>: Threading macros. (line 71) -* -sort: Other list operations. - (line 350) -* -splice: Maps. (line 90) -* -splice-list: Maps. (line 110) -* -split-at: Partitioning. (line 8) -* -split-on: Partitioning. (line 28) -* -split-when: Partitioning. (line 46) -* -split-with: Partitioning. (line 17) -* -sum: Reductions. (line 159) -* -table: Other list operations. - (line 190) -* -table-flat: Other list operations. - (line 209) -* -tails: Reductions. (line 213) -* -take: Sublist selection. (line 101) -* -take-last: Sublist selection. (line 112) -* -take-while: Sublist selection. (line 146) -* -third-item: Other list operations. - (line 298) -* -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 146) -* -update-at: List to list. (line 132) -* -when-let: Binding. (line 9) -* -when-let*: Binding. (line 23) -* -zip: Other list operations. - (line 95) -* -zip-fill: Other list operations. - (line 138) -* -zip-lists: Other list operations. - (line 119) -* -zip-with: Other list operations. - (line 79) - - - -Tag Table: -Node: Top946 -Node: Installation2425 -Node: Using in a package2958 -Node: Syntax highlighting of dash functions3322 -Node: Functions3705 -Node: Maps4916 -Ref: -map5211 -Ref: -map-when5552 -Ref: -map-first6130 -Ref: -map-last6608 -Ref: -map-indexed7081 -Ref: -annotate7561 -Ref: -splice8051 -Ref: -splice-list8832 -Ref: -mapcat9294 -Ref: -copy9670 -Node: Sublist selection9874 -Ref: -filter10067 -Ref: -remove10519 -Ref: -remove-first10925 -Ref: -remove-last11452 -Ref: -remove-item11973 -Ref: -non-nil12368 -Ref: -slice12527 -Ref: -take13059 -Ref: -take-last13367 -Ref: -drop13690 -Ref: -drop-last13963 -Ref: -take-while14223 -Ref: -drop-while14573 -Ref: -select-by-indices14929 -Ref: -select-columns15443 -Ref: -select-column16149 -Node: List to list16613 -Ref: -keep16805 -Ref: -concat17308 -Ref: -flatten17605 -Ref: -flatten-n18364 -Ref: -replace18751 -Ref: -replace-first19214 -Ref: -replace-last19711 -Ref: -insert-at20201 -Ref: -replace-at20528 -Ref: -update-at20918 -Ref: -remove-at21409 -Ref: -remove-at-indices21897 -Node: Reductions22479 -Ref: -reduce-from22648 -Ref: -reduce-r-from23414 -Ref: -reduce24181 -Ref: -reduce-r24910 -Ref: -reductions-from25781 -Ref: -reductions-r-from26496 -Ref: -reductions27221 -Ref: -reductions-r27846 -Ref: -count28481 -Ref: -sum28705 -Ref: -running-sum28894 -Ref: -product29187 -Ref: -running-product29396 -Ref: -inits29709 -Ref: -tails29957 -Ref: -common-prefix30204 -Ref: -common-suffix30501 -Ref: -min30798 -Ref: -min-by31024 -Ref: -max31547 -Ref: -max-by31772 -Node: Unfolding32300 -Ref: -iterate32539 -Ref: -unfold32984 -Node: Predicates33792 -Ref: -any?33916 -Ref: -all?34236 -Ref: -none?34566 -Ref: -only-some?34868 -Ref: -contains?35353 -Ref: -same-items?35742 -Ref: -is-prefix?36127 -Ref: -is-suffix?36450 -Ref: -is-infix?36773 -Node: Partitioning37127 -Ref: -split-at37315 -Ref: -split-with37600 -Ref: -split-on38003 -Ref: -split-when38679 -Ref: -separate39319 -Ref: -partition39761 -Ref: -partition-all40213 -Ref: -partition-in-steps40641 -Ref: -partition-all-in-steps41138 -Ref: -partition-by41623 -Ref: -partition-by-header42005 -Ref: -partition-after-pred42609 -Ref: -partition-before-pred42953 -Ref: -partition-before-item43304 -Ref: -partition-after-item43615 -Ref: -group-by43921 -Node: Indexing44358 -Ref: -elem-index44560 -Ref: -elem-indices44955 -Ref: -find-index45338 -Ref: -find-last-index45827 -Ref: -find-indices46331 -Ref: -grade-up46739 -Ref: -grade-down47142 -Node: Set operations47552 -Ref: -union47735 -Ref: -difference48177 -Ref: -intersection48594 -Ref: -powerset49031 -Ref: -permutations49244 -Ref: -distinct49544 -Node: Other list operations49922 -Ref: -rotate50147 -Ref: -repeat50517 -Ref: -cons*50780 -Ref: -snoc51167 -Ref: -interpose51580 -Ref: -interleave51878 -Ref: -zip-with52247 -Ref: -zip52964 -Ref: -zip-lists53796 -Ref: -zip-fill54497 -Ref: -unzip54820 -Ref: -cycle55565 -Ref: -pad55938 -Ref: -table56261 -Ref: -table-flat57050 -Ref: -first58058 -Ref: -some58430 -Ref: -last58739 -Ref: -first-item59073 -Ref: -second-item59489 -Ref: -third-item59769 -Ref: -fourth-item60047 -Ref: -fifth-item60313 -Ref: -last-item60575 -Ref: -butlast60867 -Ref: -sort61114 -Ref: -list61603 -Ref: -fix61934 -Node: Tree operations62474 -Ref: -tree-seq62670 -Ref: -tree-map63528 -Ref: -tree-map-nodes63971 -Ref: -tree-reduce64821 -Ref: -tree-reduce-from65703 -Ref: -tree-mapreduce66304 -Ref: -tree-mapreduce-from67164 -Ref: -clone68450 -Node: Threading macros68778 -Ref: ->68923 -Ref: ->>69414 -Ref: -->69919 -Ref: -as->70475 -Ref: -some->70930 -Ref: -some->>71304 -Ref: -some-->71740 -Node: Binding72211 -Ref: -when-let72423 -Ref: -when-let*72908 -Ref: -if-let73431 -Ref: -if-let*73826 -Ref: -let74443 -Ref: -let*80533 -Ref: -lambda81473 -Ref: -setq82270 -Node: Side-effects83086 -Ref: -each83280 -Ref: -each-while83687 -Ref: -each-indexed84047 -Ref: -each-r84565 -Ref: -each-r-while84998 -Ref: -dotimes85373 -Ref: -doto85676 -Ref: --doto86104 -Node: Destructive operations86379 -Ref: !cons86552 -Ref: !cdr86758 -Node: Function combinators86953 -Ref: -partial87227 -Ref: -rpartial87623 -Ref: -juxt88026 -Ref: -compose88458 -Ref: -applify89011 -Ref: -on89442 -Ref: -flip89968 -Ref: -const90280 -Ref: -cut90619 -Ref: -not91105 -Ref: -orfn91415 -Ref: -andfn91849 -Ref: -iteratefn92344 -Ref: -fixfn93047 -Ref: -prodfn94610 -Node: Development95678 -Node: Contribute96027 -Node: Changes96775 -Node: Contributors99773 -Node: Index101392 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/dash-20200524.1947/dir b/elpa/dash-20200524.1947/dir deleted file mode 100644 index 49b1700..0000000 --- a/elpa/dash-20200524.1947/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 |