; Cartesian product of elements of menu
(def choices (menu (o result '()))
(if menu
(each x (car menu)
(choices (cdr menu) (join result (list x))))
(prall result "\n" " ")))
(choices (list
(list "small" "medium" "large")
(list "vanilla" "ultra chocolate" "lychee" "rum raisin" "ginger")
(list "cone" "cup")))
Ah, I was wondering why append wasn't working, haha. Now I recall reading the source about how Robert Morris thought it was better to overload + for join -- which still seems to work, by the way.
Also, come to think of a nit-picky issue, optional args will default to nil = '(), so you could just as well say:
(def choices (menu (o result))
(if menu
(each x (car menu)
(choices (cdr menu) (+ result (list x))))
(prall result "\n" " ")))
Not that it matters all that much.
One artifact I notice is that, since it returns nil but is only printing a newline at the beginning, the printout ends with "large ginger cupnil". I suppose, to avoid that in the repl, you could slap a (prn) at the end of the function definition or use the aforementioned (do ...) block. I got to thinking it might also be nice to have a prnall, but then I noticed that this is just prn:
(def choices (menu (o result))
(if menu
(each x (car menu)
(choices (cdr menu) (+ result (list x))))
(apply prn (intersperse " " result))))
Though this could be cleaner with prnall:
(def prnall args
(do1 (apply prall args) (prn)))
At any rate, all these thoughts are very pedantic -- but then, so am I.