[plt-scheme] Re: matching/dispatching a la Erlang

From: Benjamin Simon (ben at amazingmedia.com)
Date: Mon Sep 1 15:14:02 EDT 2003

>>>>> "JAS" == Jens Axel Søgaard <jensaxel at soegaard.net> writes:

 JAS>   For list-related administrative tasks:
 JAS>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme

 JAS> William Sprague wrote:

 >> I want to be able to do something like the following, where
 >> "case-on-steroids" is my desired operator:
 >> 
 >> (define (choose input)
 >> (case-on-steroids (X Y)       ; define X and Y as free variables
 >> ((X X Y) (+ X Y))           ; matches (input 1 1 2), bind X->1, Y-
 >> >2     ((1 X (2 Y) X) (* X Y))     ; matches (input 1 100 '(2 300)
 >> 100)                                 ; X->100, Y->300
 >> (_ 'whatever))))            ; matches anything no bindings

 JAS> Here is my take on your example:
 [`chose' implemented above in a not-so-sexy way]
 JAS> If there is an easier way to express that the two values
 JAS> called x1 and x2 above must be equal - I'd like to see it.

Thanks to this thread, I've been inspired to check out the whole match
package further. I've learned two things:

(1) There's a site dedicated to maintaining the match code, which gives
    some examples of its use and provides a manual that also gives lots
    of info. Check it out at:
    http://sol.cs.wcu.edu/~bhauman/scheme/pattern.php

(2) The most recent version of the match code, distributed with
    plt-scheme 205, supports the ability to use two variables of the
    same name to imply equality. (I think a previous poster mentioned
    that this new functionality was in v205, but was a bit ambiguous
    about what exactly *was* possible). [1]

Given my new found knowledge I translated a few examples that I've seen
in Erlang into scheme (I've included them below). This seemed to work
out pretty well, and perhaps I'll try to use pattern matching in my next
project...

-Ben


[1] -- Hmmm, I couldn't get the match code with v205 to work, instead I
had to use the match package from the site listed above. Either way, I
got it to work.



;------------------------------------------------------------------------
;;
;; Ben play's with pattern matching:
;;


; I had to use the latest version of match
; from http://sol.cs.wcu.edu/~bhauman/scheme/pattern.php
(require (lib "match.ss" "match-2-1"))

(define (choose input)
  (match input
    [(1 x (2 y)) (* x y)]
    [(x x y)     (+ x y)]
    [_           'whatever]))

(choose '(1 2 (2 100)))  ; => 200
(choose '(3 3 9))        ; => 12
(choose '(3 4 9))        ; => 'whatever

(define member?
  (match-lambda* [(x (x . _)) #t]
                 [(x (_ . y)) (member? x y)]
                 [(x ())      #f]))

(member? 10 '(1 2 3 10 9 8))    ; => #t
(member? 'foo '(1 2 3 10 9 8))  ; => #f
(member? 10 '())                ; => #f

(define fact
  (match-lambda
   [0 1]
   [x (* x (fact (- x 1)))]))

(fact 0)  ; => 1
(fact 9)  ; => 362880
(fact 3)  ; => 6

(define area
  (match-lambda
   [('square x)    (* x x)]
   [('rectangle x y)  (* x y)]
   [('circle    r)    (* 3.14 r r)]))

(define *shapes* 
  '((square 5)
    (rectangle 3 4)
    (circle 9)))
(map area *shapes*) ; => (25 12 235.34)


Posted on the users mailing list.