The previous code is wrong. Sorry.
Let's write a function that associates each index of a list with a different index of the list itself.
Now if lst has only one value, the function should loop (because it's not possible to select an index other than 0):
If lst has more than one value, the function should work correctly:
Because 'until' (and 'while') also have an internal variable $idx.
So we're not comparing the generated value 'idx' to $idx from 'dolist', but to $idx from 'until'.
To fix this, we need to copy the value '$idx' from 'dolist' into a variable and apply it within the 'until' loop.
Let's write a function that associates each index of a list with a different index of the list itself.
Code Select
(define (sel-idx lst)
(let ((out '()) (len (length lst)))
(dolist (el lst)
; select and index of the list different from the current
(while (= (setq idx (rand len)) $idx))
;(println "coppia: " $idx idx)
(push (list $idx idx) out -1))
out))
Now if lst has only one value, the function should loop (because it's not possible to select an index other than 0):
Code Select
(sel-idx '(1))
;-> ((0 0)) --> ERRORIf lst has more than one value, the function should work correctly:
Code Select
(sel-idx '(1 2))
;-> ((0 1) (1 0)) --> OK
(sel-idx '(1 2))
;-> ((0 1) (1 1)) --> ERROR
Why doesn't the function produce correct results?Because 'until' (and 'while') also have an internal variable $idx.
So we're not comparing the generated value 'idx' to $idx from 'dolist', but to $idx from 'until'.
To fix this, we need to copy the value '$idx' from 'dolist' into a variable and apply it within the 'until' loop.
Code Select
(define (sel-idx-ok lst)
(let ((out '()) (len (length lst)) (tmp 0))
(dolist (el lst)
(setq tmp $idx)
; select and index of the list different from the current
(while (= (setq idx (rand len)) tmp))
;(println "coppia: " $idx idx)
(push (list tmp idx) out -1))
out))
(sel-idx-ok '(1))
;-> ... --> infinite loop
(sel-idx-ok '(1 2))
;-> ((0 1) (1 0)) --> OK
(sel-idx '(0 1 2 3 4 5 6 7 8 9))
;-> ((0 4) (1 9) (2 4) (3 8) (4 8) (5 9) (6 1) (7 1) (8 6) (9 6))