[plt-scheme] ML pattern programming macro in scheme
Paulo-
Here are the first three of your examples, written with the
MATCH-LAMBDA special form, which is part of the standard match.ss
library.
(require (lib "match.ss"))
(define lengthvec (match-lambda [(x y) (sqrt (+ (* x x) (* y y)))]))
(define addvec (match-lambda [((x1 y1) (x2 y2)) (list (+ x1 x2) (+
y1 y2))]))
(define negvec (match-lambda [(x y) (list (- x) (- y))]))
Its a little more wordy than your define/pat form, but also much more
powerful (A: you can actually list the different possible input cases
(e.g. you can write LENGTH using it, B: you can match structural
values, vectors, etc. C. You can use an ellipsis to match the
Kleene-star of a pattern)
-Felix
Maybe I'm missing some particular feature
On Mar 3, 2004, at 7:02 PM, 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,
>
> --
>
> Paulo J. Matos : pocm [_at_] mega . ist . utl . pt
> Instituto Superior Tecnico - Lisbon
> Computer and Software Eng. - A.I.
> - > http://mega.ist.utl.pt/~pocm
> ---
> -> God had a deadline...
> So, he wrote it all in Lisp!
>
>
----
"there's the line...and then there's josh" -nestler