[plt-scheme] ML pattern programming macro in scheme

From: Guillaume Marceau (gmarceau at cs.brown.edu)
Date: Wed Mar 3 19:23:15 EST 2004

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,



Posted on the users mailing list.