[CM] c?r?
Kjetil S. Matheussen
k.s.matheussen at notam02.no
Fri Apr 9 14:44:10 PDT 2010
That's really beautiful. :-)
On Fri, 9 Apr 2010, Bill Schottstaedt wrote:
> I was grumbling to myself that no one should have to count
> cars and cdrs, then thought of this macro:
>
> (define-macro (c?r path)
> ;; here "path" is a list and "X" marks the spot in it that we are trying to access
> ;; (a (b ((c X)))) -- anything after the X is ignored, other symbols are just placeholders
> ;; c?r returns a function that gets X
>
> ;; (c?r (a b X)) -> caddr,
> ;; (c?r (a (b X))) -> cadadr
> ;; ((c?r (a a a X)) '(1 2 3 4 5 6)) -> 4
> ;; ((c?r (a (b c X))) '(1 (2 3 4))) -> 4
> ;; ((c?r (((((a (b (c (d (e X)))))))))) '(((((1 (2 (3 (4 (5 6)))))))))) -> 6
> ;; ((c?r (((((a (b (c (X (e f)))))))))) '(((((1 (2 (3 (4 (5 6)))))))))) -> 4
> ;; (procedure-source (c?r (((((a (b (c (X (e f))))))))))) -> (lambda (lst) (car (car (cdr (car (cdr (car (cdr
> (car (car (car (car lst))))))))))))
>
> (define (X-marks-the-spot accessor tree)
> (if (pair? tree)
> (or (X-marks-the-spot (cons 'car accessor) (car tree))
> (X-marks-the-spot (cons 'cdr accessor) (cdr tree)))
> (if (eq? tree 'X)
> accessor
> #f)))
>
> (let ((accessor (X-marks-the-spot '() path)))
> (if (not accessor)
> (error "can't find the spot! ~A" path)
> (let ((len (length accessor)))
> (if (< len 5) ; it's a built-in function
> (let ((name (make-string (+ len 2))))
> (set! (name 0) #\c)
> (set! (name (+ len 1)) #\r)
> (do ((i 0 (+ i 1))
> (a accessor (cdr a)))
> ((= i len))
> (set! (name (+ i 1)) (if (eq? (car a) 'car) #\a #\d)))
> (string->symbol name))
> (let ((body 'lst)) ; make a new function to find the spot
> (for-each
> (lambda (f)
> (set! body (list f body)))
> (reverse accessor))
> `(lambda (lst) ,body)))))))
>
>
> _______________________________________________
> Cmdist mailing list
> Cmdist at ccrma.stanford.edu
> http://ccrma-mail.stanford.edu/mailman/listinfo/cmdist
>
More information about the Cmdist
mailing list