diff options
| author | Nicolas Petton | 2015-05-05 22:10:32 +0200 |
|---|---|---|
| committer | Nicolas Petton | 2015-05-05 22:10:32 +0200 |
| commit | 4ac426a1b90912ea947d46a57b6fcbbbf7586da1 (patch) | |
| tree | bbf748a53aca52aeac72df288e9cfbac3b951580 /lisp | |
| parent | 0508aa26705b3507d9afac54ada4eac47f8cf8a5 (diff) | |
| parent | 8cb4b4f98aa2758a016df25e39ff48cf132ed39c (diff) | |
| download | emacs-4ac426a1b90912ea947d46a57b6fcbbbf7586da1.tar.gz emacs-4ac426a1b90912ea947d46a57b6fcbbbf7586da1.zip | |
Merge branch 'seq-let'
Diffstat (limited to 'lisp')
| -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 @@ | |||
| 4 | 4 | ||
| 5 | ;; Author: Nicolas Petton <nicolas@petton.fr> | 5 | ;; Author: Nicolas Petton <nicolas@petton.fr> |
| 6 | ;; Keywords: sequences | 6 | ;; Keywords: sequences |
| 7 | ;; Version: 1.5 | 7 | ;; Version: 1.6 |
| 8 | ;; Package: seq | 8 | ;; Package: seq |
| 9 | 9 | ||
| 10 | ;; Maintainer: emacs-devel@gnu.org | 10 | ;; Maintainer: emacs-devel@gnu.org |
| @@ -40,6 +40,11 @@ | |||
| 40 | ;; | 40 | ;; |
| 41 | ;; All functions are tested in test/automated/seq-tests.el | 41 | ;; All functions are tested in test/automated/seq-tests.el |
| 42 | 42 | ||
| 43 | ;;; TODO: | ||
| 44 | |||
| 45 | ;; - Add a pcase macro named using `pcase-defmacro' that `seq-let' | ||
| 46 | ;; - could wrap. | ||
| 47 | |||
| 43 | ;;; Code: | 48 | ;;; Code: |
| 44 | 49 | ||
| 45 | (defmacro seq-doseq (spec &rest body) | 50 | (defmacro seq-doseq (spec &rest body) |
| @@ -65,6 +70,14 @@ Evaluate BODY with VAR bound to each element of SEQ, in turn. | |||
| 65 | (pop ,index)))) | 70 | (pop ,index)))) |
| 66 | ,@body))))) | 71 | ,@body))))) |
| 67 | 72 | ||
| 73 | (defmacro seq-let (args seq &rest body) | ||
| 74 | "Bind the variables in ARGS to the elements of SEQ then evaluate BODY." | ||
| 75 | (declare (indent 2) (debug t)) | ||
| 76 | (let ((seq-var (make-symbol "seq"))) | ||
| 77 | `(let* ((,seq-var ,seq) | ||
| 78 | ,@(seq--make-bindings args seq-var)) | ||
| 79 | ,@body))) | ||
| 80 | |||
| 68 | (defun seq-drop (seq n) | 81 | (defun seq-drop (seq n) |
| 69 | "Return a subsequence of SEQ without its first N elements. | 82 | "Return a subsequence of SEQ without its first N elements. |
| 70 | The result is a sequence of the same type as SEQ. | 83 | 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'." | |||
| 336 | (defun seq--activate-font-lock-keywords () | 349 | (defun seq--activate-font-lock-keywords () |
| 337 | "Activate font-lock keywords for some symbols defined in seq." | 350 | "Activate font-lock keywords for some symbols defined in seq." |
| 338 | (font-lock-add-keywords 'emacs-lisp-mode | 351 | (font-lock-add-keywords 'emacs-lisp-mode |
| 339 | '("\\<seq-doseq\\>"))) | 352 | '("\\<seq-doseq\\>" "\\<seq-let\\>"))) |
| 353 | |||
| 354 | (defun seq--make-bindings (args seq &optional bindings) | ||
| 355 | "Return a list of bindings of the variables in ARGS to the elements of SEQ. | ||
| 356 | if BINDINGS is non-nil, append new bindings to it, and | ||
| 357 | return BINDINGS." | ||
| 358 | (let ((index 0) | ||
| 359 | (rest-bound nil)) | ||
| 360 | (seq-doseq (name args) | ||
| 361 | (unless rest-bound | ||
| 362 | (pcase name | ||
| 363 | ((pred seq-p) | ||
| 364 | (setq bindings (seq--make-bindings (seq--elt-safe args index) | ||
| 365 | `(seq--elt-safe ,seq ,index) | ||
| 366 | bindings))) | ||
| 367 | (`&rest | ||
| 368 | (progn (push `(,(seq--elt-safe args (1+ index)) | ||
| 369 | (seq-drop ,seq ,index)) | ||
| 370 | bindings) | ||
| 371 | (setq rest-bound t))) | ||
| 372 | (t | ||
| 373 | (push `(,name (seq--elt-safe ,seq ,index)) bindings)))) | ||
| 374 | (setq index (1+ index))) | ||
| 375 | bindings)) | ||
| 376 | |||
| 377 | (defun seq--elt-safe (seq n) | ||
| 378 | "Return element of SEQ at the index N. | ||
| 379 | If no element is found, return nil." | ||
| 380 | (when (or (listp seq) | ||
| 381 | (and (sequencep seq) | ||
| 382 | (> (seq-length seq) n))) | ||
| 383 | (seq-elt seq n))) | ||
| 340 | 384 | ||
| 341 | (defalias 'seq-copy #'copy-sequence) | 385 | (defalias 'seq-copy #'copy-sequence) |
| 342 | (defalias 'seq-elt #'elt) | 386 | (defalias 'seq-elt #'elt) |