guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

match-abs


From: Stefan Israelsson Tampe
Subject: match-abs
Date: Sun, 29 Aug 2010 23:56:42 +0200
User-agent: KMail/1.13.5 (Linux/2.6.34-12-desktop; KDE/4.4.4; x86_64; ; )

Hi,

I've hacked on extension on ice-9/match for making modular matching possible
with a reasonable interface. Here is an example,

;; new version of match with modular matching abatractions see 
;; http://gitorious.org/guile-unify/guile-
unify/blobs/master/module/ice-9/match-abs.scm
(use-modules (ice-9 match-abs))

;;Example, notice ((<op> A B)) means first result of <op> is stored in A and 
the second is in B
(define (<op> X)
  (match abstractions ((<op> A B))
         X
         (['- <op> <op>  . L]  (cons  (- B A)  L))
         (['+ <op> <op>  . L]  (cons  (+ A B)  L))
         (['* <op> <op>  . L]  (cons  (* A B)  L))
         (['/ <op> <op>  . L]  (cons  (/ B A)  L))
         ([(? number? X) . L]  (cons     X     L))
         (_                    (cons    #f    #f))))

;;alternatively one can use the more general but wordy <> notation
(define (<op> X)
  (match X
         (['- (<> <op> A) (<> <op> B)  . L]  (cons  (- A B)  L))
         (['+ (<> <op> A) (<> <op> B)  . L]  (cons  (+ A B)  L))
         (['* (<> <op> A) (<> <op> B)  . L]  (cons  (* A B)  L))
         (['/ (<> <op> A) (<> <op> B)  . L]  (cons  (/ A B)  L))
         ([(? number? X) . L]  (cons     X     L))
         (_                    (cons    #f    #f))))

(define (rpn x) (car (<op> (reverse x))))

;;and (rpn '(2 4 * 1 -)) evaluates to 7


So e.g. the protocol for a matcher is that the last argument for a matcher
is the list to match on. The matcher should return a cons cell, if the car
element is false the match fails and else it is the value of the match. the 
second argument represent the rest of the list after the match has been 
removed. 

More examples, this is a gready matcher that tries to match as much as 
possible
It has a curry feature thats cool.

(define (<*> <a> . r)
  (define (f x res)
    (let ((ret (<a> x)))
      (if (car ret)
          (f (cdr ret) (cons (car ret res)))
          (cons (reverse res) x))))
  (if (pair? r)
      (f (car r) '())
      (lambda (l) (f l '()))))


(define (<alternate> <a> <b> l)
  (match abstractions ((<a> a1 a2)(<b> b1 b2))
         l  
         ([<a> <b> <a> <b> . ls]  (cons (apend a1 a2 b1 b2) ls))
         (_                       (cons #f #f))))


and now we can do something like this thanks to the currying

(match abstractions ((<alternate> alt) (<*> m3))
       X
       ((<alternate> (<*> <match1>) (<*> <match2>) (<*> <match3>))
        (append m3 alt)))

Note here <match1>, ... , <match3> are all function arguments and does not
represent a part of the match hence these abstractions are not mensioned
at the abstraction definitions also the first two <*> is at function postions 
and also in function position. also this means that (<*> <match1>) will need
to use the currying feature of <*> in order to function correctly. So here we 
se a nice application of currying.

(match abstractions ((<alternate> alt) (<*> m3))
       X
       ((<> (<alternate> (<*> <match1>) (<*> <match2>) alt)(<*> <match3>))
        (append m3 alt)))

Using <> things gets clearer.


So Is this something that can be of any interests? It's been a good exercise
in syntax-case macro writing and I do feel like I'm mastering the ice-9 match
that we are currently working on so however we choose, we do not loose.

Note 1, I've used a similar tool in parsing prolog, but I do not use this for
operatore precedence handling.

Note 2. One can device a proper backtracking methodology so that we could
have matched  (bbbbbbba) with matcher ((<*> <b>) 'b 'a), where <b> matches b, 
(<*> <b>) will consume all the b:s and not backtrack when the rest fails 
((and 'b bs) ... 'b 'a) will do the trick though!)
but I feel that using prolog or the scheme version of it (schelog?) in the 
first place is a better tool to achive this. One need to play with 
continuatons
very much like working with the prolog code I made. If you like I can make 
that
work and/or.

Note 3 using (defmacro (/. p r) 
               `(lambda (l) (match l 
                                   ((,p . l) (cons ,r  l)) 
                                   (_       (cons #f #f)))))
or a correct define-syntax version of it means that we could write a matcher
like ((<*> (/. 'b 'b)) 'b 'a) in the above syntax

Cheers
Stefan

      
   





reply via email to

[Prev in Thread] Current Thread [Next in Thread]