]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/seq.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / emacs-lisp / seq.el
index d0c2d24b015e446f424bb646ee2230480d6e99bf..92f0ad78566c78cfa46f38cd77b8c09f6bdb6ae3 100644 (file)
@@ -1,10 +1,10 @@
 ;;; seq.el --- Sequence manipulation functions  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Keywords: sequences
-;; Version: 2.1
+;; Version: 2.14
 ;; Package: seq
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -46,7 +46,7 @@
 ;; - `seq-elt'
 ;; - `seq-length'
 ;; - `seq-do'
-;; - `seq-p'
+;; - `seqp'
 ;; - `seq-subseq'
 ;; - `seq-into-sequence'
 ;; - `seq-copy'
@@ -57,7 +57,7 @@
 ;;; Code:
 
 (eval-when-compile (require 'cl-generic))
-(require 'cl-extra) ;; for cl-subseq
+(require 'cl-lib) ;; for cl-subseq
 
 (defmacro seq-doseq (spec &rest body)
   "Loop over a sequence.
@@ -79,7 +79,7 @@ corresponding element of SEQUENCE.
 
 Extra elements of the sequence are ignored if fewer PATTERNS are
 given, and the match does not fail."
-  `(and (pred seq-p)
+  `(and (pred seqp)
         ,@(seq--make-pcase-bindings patterns)))
 
 (defmacro seq-let (args sequence &rest body)
@@ -117,7 +117,7 @@ Return SEQUENCE."
 
 (defalias 'seq-each #'seq-do)
 
-(cl-defgeneric seq-p (sequence)
+(cl-defgeneric seqp (sequence)
   "Return non-nil if SEQUENCE is a sequence, nil otherwise."
   (sequencep sequence))
 
@@ -144,10 +144,37 @@ if positive or too small if negative)."
             sequence)
     (nreverse result)))
 
+(defun seq-map-indexed (function sequence)
+  "Return the result of applying FUNCTION to each element of SEQUENCE.
+Unlike `seq-map', FUNCTION takes two arguments: the element of
+the sequence, and its index within the sequence."
+  (let ((index 0))
+    (seq-map (lambda (elt)
+               (prog1
+                   (funcall function elt index)
+                 (setq index (1+ index))))
+             sequence)))
+
+
 ;; faster implementation for sequences (sequencep)
 (cl-defmethod seq-map (function (sequence sequence))
   (mapcar function sequence))
 
+(cl-defgeneric seq-mapn (function sequence &rest sequences)
+  "Like `seq-map' but FUNCTION is mapped over all SEQUENCES.
+The arity of FUNCTION must match the number of SEQUENCES, and the
+mapping stops on the shortest sequence.
+Return a list of the results.
+
+\(fn FUNCTION SEQUENCES...)"
+  (let ((result nil)
+        (sequences (seq-map (lambda (s) (seq-into s 'list))
+                            (cons sequence sequences))))
+    (while (not (memq nil sequences))
+      (push (apply function (seq-map #'car sequences)) result)
+      (setq sequences (seq-map #'cdr sequences)))
+    (nreverse result)))
+
 (cl-defgeneric seq-drop (sequence n)
   "Remove the first N elements of SEQUENCE and return the result.
 The result is a sequence of the same type as SEQUENCE.
@@ -191,6 +218,16 @@ The result is a sequence of the same type as SEQUENCE."
 (cl-defmethod seq-sort (pred (list list))
   (sort (seq-copy list) pred))
 
+(defun seq-sort-by (function pred sequence)
+  "Sort SEQUENCE using PRED as a comparison function.
+Elements of SEQUENCE are transformed by FUNCTION before being
+sorted.  FUNCTION must be a function of one argument."
+  (seq-sort (lambda (a b)
+              (funcall pred
+                       (funcall function a)
+                       (funcall function b)))
+            sequence))
+
 (cl-defgeneric seq-reverse (sequence)
   "Return a sequence with elements of SEQUENCE in reverse order."
   (let ((result '()))
@@ -418,7 +455,7 @@ SEQUENCE must be a sequence of numbers or markers."
   "Return a list of `(seq ...)' pcase patterns from the argument list ARGS."
   (cons 'seq
         (seq-map (lambda (elt)
-                   (if (seq-p elt)
+                   (if (seqp elt)
                        (seq--make-pcase-patterns elt)
                      elt))
                  args)))