>From 77984f5705f478275b865e7c3105ceca9380007e Mon Sep 17 00:00:00 2001 From: Damien Cassou Date: Fri, 21 Oct 2016 07:53:08 +0200 Subject: [PATCH] Add seq-random-elt to seq.el * lisp/emacs-lisp/seq.el (seq-random-elt): Add function to return a random element from it's sequence parameter. * test/lisp/emacs-lisp/seq-tests.el (test-seq-random-elt-take-all test-seq-random-elt-return-nil): Test the new function * doc/lispref/sequences.texi: Document the new function --- doc/lispref/sequences.texi | 20 ++++++++++++++++++++ lisp/emacs-lisp/seq.el | 8 +++++++- test/lisp/emacs-lisp/seq-tests.el | 15 +++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 08e5e3a..f06a615 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -1037,6 +1037,26 @@ Sequence Functions @end example @end defmac address@hidden seq-random-elt sequence + This function returns an element of @var{sequence} taken at random. If @var{sequence} is nil, the function returns nil. + address@hidden address@hidden +(seq-random-elt [1 2 3 4]) address@hidden 3 +(seq-random-elt [1 2 3 4]) address@hidden 2 +(seq-random-elt [1 2 3 4]) address@hidden 4 +(seq-random-elt [1 2 3 4]) address@hidden 2 +(seq-random-elt [1 2 3 4]) address@hidden 1 address@hidden group address@hidden example + + If @var{sequence} is nil, the function returns nil. address@hidden defun @node Arrays @section Arrays diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 9859f28..9ece928 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -4,7 +4,7 @@ ;; Author: Nicolas Petton ;; Keywords: sequences -;; Version: 2.18 +;; Version: 2.19 ;; Package: seq ;; Maintainer: address@hidden @@ -476,6 +476,12 @@ seq--elt-safe "Return element of SEQUENCE at the index N. If no element is found, return nil." (ignore-errors (seq-elt sequence n))) + +(cl-defgeneric seq-random-elt (sequence) + "Return a random element from SEQUENCE. +Return nil if SEQUENCE is nil." + (when sequence + (seq-elt sequence (random (seq-length sequence))))) ;;; Optimized implementations for lists diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el index c2065c6..a6f26be 100644 --- a/test/lisp/emacs-lisp/seq-tests.el +++ b/test/lisp/emacs-lisp/seq-tests.el @@ -28,6 +28,7 @@ (require 'ert) (require 'seq) +(require 'map) (defmacro with-test-sequences (spec &rest body) "Successively bind VAR to a list, vector, and string built from SEQ. @@ -371,5 +372,19 @@ test-sequences-oddp (should (equal (seq-sort-by #'seq-length #'> seq) ["xxx" "xx" "x"])))) +(ert-deftest test-seq-random-elt-take-all () + (let ((seq '(a b c d e)) + (count '())) + (should (= 0 (map-length count))) + (dotimes (_ 1000) + (let ((random-elt (seq-random-elt seq))) + (map-put count + random-elt + (map-elt count random-elt 0)))) + (should (= 5 (map-length count))))) + +(ert-deftest test-seq-random-elt-return-nil () + (should (null (seq-random-elt nil)))) + (provide 'seq-tests) ;;; seq-tests.el ends here -- 2.10.0