diff options
author | Nicolas Petton <nicolas@petton.fr> | 2015-05-05 22:10:32 +0200 |
---|---|---|
committer | Nicolas Petton <nicolas@petton.fr> | 2015-05-05 22:10:32 +0200 |
commit | 4ac426a1b90912ea947d46a57b6fcbbbf7586da1 (patch) | |
tree | bbf748a53aca52aeac72df288e9cfbac3b951580 /lisp/emacs-lisp/seq.el | |
parent | 0508aa26705b3507d9afac54ada4eac47f8cf8a5 (diff) | |
parent | 8cb4b4f98aa2758a016df25e39ff48cf132ed39c (diff) | |
download | emacs-4ac426a1b90912ea947d46a57b6fcbbbf7586da1.tar.gz |
Merge branch 'seq-let'
Diffstat (limited to 'lisp/emacs-lisp/seq.el')
-rw-r--r-- | lisp/emacs-lisp/seq.el | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 456debf5f7c..f1633ce8cd7 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -4,7 +4,7 @@ ;; Author: Nicolas Petton <nicolas@petton.fr> ;; Keywords: sequences -;; Version: 1.5 +;; Version: 1.6 ;; Package: seq ;; Maintainer: emacs-devel@gnu.org @@ -40,6 +40,11 @@ ;; ;; All functions are tested in test/automated/seq-tests.el +;;; TODO: + +;; - Add a pcase macro named using `pcase-defmacro' that `seq-let' +;; - could wrap. + ;;; Code: (defmacro seq-doseq (spec &rest body) @@ -65,6 +70,14 @@ Evaluate BODY with VAR bound to each element of SEQ, in turn. (pop ,index)))) ,@body))))) +(defmacro seq-let (args seq &rest body) + "Bind the variables in ARGS to the elements of SEQ then evaluate BODY." + (declare (indent 2) (debug t)) + (let ((seq-var (make-symbol "seq"))) + `(let* ((,seq-var ,seq) + ,@(seq--make-bindings args seq-var)) + ,@body))) + (defun seq-drop (seq n) "Return a subsequence of SEQ without its first N elements. The result is a sequence of the same type as SEQ. @@ -336,7 +349,38 @@ This is an optimization for lists in `seq-take-while'." (defun seq--activate-font-lock-keywords () "Activate font-lock keywords for some symbols defined in seq." (font-lock-add-keywords 'emacs-lisp-mode - '("\\<seq-doseq\\>"))) + '("\\<seq-doseq\\>" "\\<seq-let\\>"))) + +(defun seq--make-bindings (args seq &optional bindings) + "Return a list of bindings of the variables in ARGS to the elements of SEQ. +if BINDINGS is non-nil, append new bindings to it, and +return BINDINGS." + (let ((index 0) + (rest-bound nil)) + (seq-doseq (name args) + (unless rest-bound + (pcase name + ((pred seq-p) + (setq bindings (seq--make-bindings (seq--elt-safe args index) + `(seq--elt-safe ,seq ,index) + bindings))) + (`&rest + (progn (push `(,(seq--elt-safe args (1+ index)) + (seq-drop ,seq ,index)) + bindings) + (setq rest-bound t))) + (t + (push `(,name (seq--elt-safe ,seq ,index)) bindings)))) + (setq index (1+ index))) + bindings)) + +(defun seq--elt-safe (seq n) + "Return element of SEQ at the index N. +If no element is found, return nil." + (when (or (listp seq) + (and (sequencep seq) + (> (seq-length seq) n))) + (seq-elt seq n))) (defalias 'seq-copy #'copy-sequence) (defalias 'seq-elt #'elt) |