unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Stefan Israelsson Tampe <stefan.tampe@spray.se>
To: guile-devel@gnu.org
Subject: match-abs
Date: Sun, 29 Aug 2010 23:56:42 +0200	[thread overview]
Message-ID: <201008292356.42854.stefan.tampe@spray.se> (raw)

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	other threads:[~2010-08-29 21:56 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-29 21:56 Stefan Israelsson Tampe [this message]
2010-08-30 22:55 ` match-abs Ludovic Courtès
2010-08-31 14:42   ` match-abs Ludovic Courtès
2010-09-01  9:34     ` match-abs Stefan Israelsson Tampe
2010-09-01 12:05       ` match-abs Ludovic Courtès
2010-09-01  7:30   ` match-abs Stefan Israelsson Tampe
2010-09-02 15:59     ` match-abs Ludovic Courtès
2010-09-02 18:07       ` match-abs Stefan Israelsson Tampe
2010-09-02 18:53       ` match-abs Stefan Israelsson Tampe
2010-09-02 22:46         ` match-abs Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201008292356.42854.stefan.tampe@spray.se \
    --to=stefan.tampe@spray.se \
    --cc=guile-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).