[plt-scheme] ML pattern programming macro in scheme
Search the help-desk for match.ss and plt-match.ss and your hearth will
fill with joy.
On Wed, 2004-03-03 at 19:02, Paulo Jorge de Oliveira Cantante de Matos
wrote:
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>
> Dear all,
>
> While studying SML through Paulson's book I just found nice to write
> procedures whose arguments where some kind of pattern, based on lists...
> so I though... da hell, maybe this could be useful in scheme. Since I
> never heard about any implementation with this (didn't search much
> also... heh) I implemented a very simple macro without any error
> checking, however the results were nice. Is there any interest in a
> macro like this in DrScheme, or around the scheme community? Am I
> reinventing the wheel, since it is already done?
>
> Ok, the code is as follows:
> (define-macro define/pat
> (letrec ([getpath
> (lambda (l)
> (letrec ([aux
> (lambda (los f bindings)
> (cond ([null? los]
> bindings)
> ([symbol? (car los)]
> (aux (cdr los)
> (cons 'cdr (list f))
> (cons (list (car los) (cons 'car
> (list f)))
> bindings)))
> ([list? (car los)]
> (append (aux (car los)
> (cons 'car (list f))
> null)
> (aux (cdr los)
> (cons 'cdr (list f))
> bindings)))
> (else (error "Unexpected case."))))])
> (aux l 'x null)))])
> (lambda (name pat . body)
> `(define ,name
> (lambda args
> (let ,(map (lambda (pair)
> `(,(car pair)
> (apply (lambda (x) ,(cadr pair)) args)))
> (getpath pat))
> , at body))))))
>
>
> Ok, now, here are some nice simple tests from the SML book:
> ; Length of a vector
> (define/pat lengthvec (x y)
> (sqrt (+ (* x x) (* y y))))
>
> ; Adds two vectors
> (define/pat addvec ((x1 y1) (x2 y2))
> (list (+ x1 x2) (+ y1 y2)))
>
> ; Negates a vector
> (define/pat negvec (x y)
> (list (- x) (- y)))
>
> ; Averages two numbers
> (define/pat average (x y)
> (/ (+ x y) 2))
>
> ; Subtracts two vectors
> (define/pat subvec (v1 v2)
> (addvec `(,v1 ,(negvec v2))))
>
> ; Distance between two vectors
> (define/pat distance (pairvec)
> (lengthvec (subvec pairvec)))
>
> ; Scale a vector
> (define/pat scalevec (r (x y))
> (list (* r x) (* r y)))
>
> ; And now some testing:
> (define vec1 '(2 3))
> (define vec2 '(5 4))
> (define vec3 '(-2 3))
>
> (lengthvec vec1)
> > 3.605551275463989
> (lengthvec vec3)
> > 3.605551275463989
> (addvec `(,vec1 ,vec3))
> > (0 6)
> (negvec vec3)
> > (2 -3)
> (average vec2)
> > 4 1/2
> (subvec `(,vec1 ,vec2))
> > (-3 -1)
> (distance (list `(,vec1 ,vec2)))
> > 3.1622776601683795
> (scalevec `(3 ,vec2))
> > (15 12)
>
> I know there is some boring usage of quasiquote here, I think one can
> find a way to make it easier to use define/pat, however, I've not looked
> into it and I won't for some days since I'm having a lot of work. This
> is just to let you now of some nice result so that you can comment about
> this nice macro. :D At least, it made me happy! heheh
>
> Cheers,