18 |
,@(loop for i from 0 for e in cases collect `(,i ,e)) |
,@(loop for i from 0 for e in cases collect `(,i ,e)) |
19 |
(t (error "Can't happen?! (in random-case)~%"))))) |
(t (error "Can't happen?! (in random-case)~%"))))) |
20 |
|
|
21 |
|
(defmacro rcase (&body cases) |
22 |
|
"Usage: (RCASE (<weight> <form>+)+), where <weight> is a positive real |
23 |
|
indicating the relative probability of executing the associated implicit |
24 |
|
progn." |
25 |
|
(assert cases) |
26 |
|
(let* ((weights (mapcar #'car cases)) |
27 |
|
(cumulative-weights (let ((sum 0)) |
28 |
|
(loop for w in weights collect (incf sum w)))) |
29 |
|
(total (car (last cumulative-weights))) |
30 |
|
(r (gensym))) |
31 |
|
(assert (every #'plusp weights)) |
32 |
|
`(let ((,r (random ,total))) |
33 |
|
(cond |
34 |
|
,@(loop for case in (butlast cases) |
35 |
|
for cw in cumulative-weights |
36 |
|
collect `((< ,r ,cw) ,@(cdr case))) |
37 |
|
(t ,@(cdar (last cases))))))) |
38 |
|
|
39 |
(defun random-nonnegative-real () |
(defun random-nonnegative-real () |
40 |
(if (coin 3) |
(if (coin 3) |
41 |
(random-case |
(random-case |