;; Jens Axel S\x{00F8}gaard writes: ;; ;; >> There are several noteworthy solutions, but the ;; >> shortest is from Ben Goetter: ;; ;; (define (shuffle l) ;; (map cdr ;; (sort (lambda (x y) (< (car x) (car y))) ;; (map (lambda (x) (cons (random 1.0) x)) l)))) ;; gauche (use srfi-1) (define (random _) (sys-random)) (define (shuffle l) (map cdr (sort (map (lambda (x) (cons (random 1.0) x)) l) (lambda (x y) (< (car x) (car y)))))) (print (shuffle (iota 20))) ;; ;; It's short and sweet and purely functional (modulo the side effect in ;; random). It's also O(n log n) where the usual swapping algorithm is ;; linear time, and it assumes the programmer remembers which way sort ;; wants its arguments, which I didn't. Also, if one kept the playing ;; list in a vector, the usual swapping would not need any extra space. ;; ;; Hm. Petite Chez seems to have its sort that way, and it seems stable, ;; too. Is that portable nowadays? ;; ;; ---- ;; This also works on Chicken, with the order of the argument in ;; sort exchanged and a minor variation in random. I would call it a ;; Schwartzian transform or a DSU (decorate-sort-undecorate) pattern. It ;; is not a translation of Python's shuffle, but does the same job, so ;; I will accept it as a solution of my problem ;) ;; ;; -------------------- ;; Often let* is used in the situation where a series of ;; assignments are used in an imperative language. Thus heavily use ;; of let* is normally a sign of problems, but the construct is quite ;; handy when it is needed. ;; ;; One difference between let and let* is that you can "update" several ;; variables at a time based on several old values using let where as ;; let* updates shadows the old value. ;; ;; (let ([x 0] ;; [y 0]) ;; (let ([x (+ x 1)] ;; [y (+ x 1)]) ;; (list x y)) ;; ;; => (list 1 1) ;; ;; and ;; ;; (let ([x 0] ;; [y 0]) ;; (let* ([x (+ x 1)] ;; [y (+ x 1)]) ;; (list x y)) ;; ;; => (list 1 2) ;; ;; Perhaps someone more imaginative than me can come up with a ;; real life example.