aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/lispref/sequences.texi40
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/sort.el21
3 files changed, 4 insertions, 62 deletions
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 8b4ce539669..8b06874e73c 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -440,6 +440,10 @@ where @var{predicate} is the @code{:lessp} argument. When using this
440form, sorting is always done in-place. 440form, sorting is always done in-place.
441@end defun 441@end defun
442 442
443@xref{Sorting}, for more functions that perform sorting. See
444@code{documentation} in @ref{Accessing Documentation}, for a useful
445example of @code{sort}.
446
443@cindex comparing values 447@cindex comparing values
444@cindex standard sorting order 448@cindex standard sorting order
445@anchor{definition of value<} 449@anchor{definition of value<}
@@ -476,42 +480,6 @@ Examples:
476@end example 480@end example
477@end defun 481@end defun
478 482
479Sometimes, computation of sort keys of list or vector elements is
480expensive, and therefore it is important to perform it the minimum
481number of times. By contrast, computing the sort keys of elements
482inside the @var{predicate} function passed to @code{sort} will generally
483perform this computation each time @var{predicate} is called with some
484element. If you can separate the computation of the sort key of an
485element into a function of its own, you can use the following sorting
486function, which guarantees that the key will be computed for each list
487or vector element exactly once.
488
489@cindex decorate-sort-undecorate
490@cindex Schwartzian transform
491@defun sort-on sequence predicate accessor
492This function stably sorts @var{sequence}, which can be a list, a
493vector, a bool-vector, or a string. It sorts by comparing the sort
494keys of the elements using @var{predicate}. The comparison function
495@var{predicate} accepts two arguments, the sort keys to compare, and
496should return non-@code{nil} if the element corresponding to the first
497key should sort before the element corresponding to the second key. The
498function computes a sort key of each element by calling the
499@var{accessor} function on that element; it does so exactly once for
500each element of @var{sequence}. The @var{accessor} function is called
501with a single argument, an element of @var{sequence}.
502
503This function implements what is known as @dfn{decorate-sort-undecorate}
504paradigm, or the Schwartzian transform. It basically trades CPU for
505memory, creating a temporary list with the computed sort keys, then
506mapping @code{car} over the result of sorting that temporary list.
507Unlike with @code{sort}, the return value is always a new list; the
508original @var{sequence} is left intact.
509@end defun
510
511@xref{Sorting}, for more functions that perform sorting. See
512@code{documentation} in @ref{Accessing Documentation}, for a useful
513example of @code{sort}.
514
515@cindex sequence functions in seq 483@cindex sequence functions in seq
516@cindex seq library 484@cindex seq library
517@cindex sequences, generalized 485@cindex sequences, generalized
diff --git a/etc/NEWS b/etc/NEWS
index 4a68737ba5f..eb6b3285c17 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1734,11 +1734,6 @@ ordering predicates by hand.
1734The old signature, '(sort SEQ PREDICATE)', can still be used and sorts 1734The old signature, '(sort SEQ PREDICATE)', can still be used and sorts
1735its input in-place as before. 1735its input in-place as before.
1736 1736
1737** New function 'sort-on'.
1738This function implements the Schwartzian transform, and is appropriate
1739for sorting lists when the computation of the sort key of a list
1740element can be expensive.
1741
1742** New API for 'derived-mode-p' and control of the graph of major modes. 1737** New API for 'derived-mode-p' and control of the graph of major modes.
1743 1738
1744*** 'derived-mode-p' now takes the list of modes as a single argument. 1739*** 'derived-mode-p' now takes the list of modes as a single argument.
diff --git a/lisp/sort.el b/lisp/sort.el
index 4f0d759ef8a..2ee76b6e1e3 100644
--- a/lisp/sort.el
+++ b/lisp/sort.el
@@ -478,27 +478,6 @@ sRegexp specifying key within record: \nr")
478 ;; if there was no such register 478 ;; if there was no such register
479 (error (throw 'key nil)))))))))) 479 (error (throw 'key nil))))))))))
480 480
481;;;###autoload
482(defun sort-on (sequence predicate accessor)
483 "Sort SEQUENCE by calling PREDICATE on sort keys produced by ACCESSOR.
484SEQUENCE should be the input sequence to sort.
485Elements of SEQUENCE are sorted by keys which are obtained by
486calling ACCESSOR on each element. ACCESSOR should be a function of
487one argument, an element of SEQUENCE, and should return the key
488value to be compared by PREDICATE for sorting the element.
489PREDICATE is the function for comparing keys; it is called with two
490arguments, the keys to compare, and should return non-nil if the
491first key should sort before the second key.
492The return value is always a new list.
493This function has the performance advantage of evaluating
494ACCESSOR only once for each element in the input SEQUENCE, and is
495therefore appropriate when computing the key by ACCESSOR is an
496expensive operation. This is known as the \"decorate-sort-undecorate\"
497paradigm, or the Schwartzian transform."
498 (mapcar #'car
499 (sort (mapcar #'(lambda (x) (cons x (funcall accessor x))) sequence)
500 #'(lambda (x y) (funcall predicate (cdr x) (cdr y))))))
501
502 481
503(defvar sort-columns-subprocess t) 482(defvar sort-columns-subprocess t)
504 483