[plt-scheme] ML pattern programming macro in scheme

From: Felix Klock's PLT scheme proxy (pltscheme at pnkfx.org)
Date: Wed Mar 3 19:29:12 EST 2004

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



Posted on the users mailing list.