> Here's a version that appears to be faster. It uses an accumulator > instead of a non-local variable and uses recursion over the list l2 rather > than over positions in that list, thus avoiding all of the calls to > LIST-REF and LIST-TAIL.
But it seems you still make a lot of calls to LENGTH, which similarly do needless list traversals. Here's how I would write it:
;; Returns all n-length subsets of the list l. (define (subsets l n) ;; ss prepends each n-length subset of l to little-acc, and returns ;; a list of the resulting sets, prepended to big-acc. len must be ;; the length of l. (let ss ((l l) (len (length l)) (n n) (little-acc '()) (big-acc '())) (cond ((zero? n) (cons little-acc big-acc)) ((< len n) big-acc) (else (ss (cdr l) (- len 1) (- n 1) (cons (car l) little-acc) (ss (cdr l) (- len 1) n little-acc big-acc))))))