Difficulty with match

Started by Jeff, May 20, 2008, 08:14:19 AM

Previous topic - Next topic

Jeff

I can't get this to match.  The match list is created programmatically and the list it is being matched against is stored in another list.


(match '((square ?)) '((square s)))

When I type the code into the repl, it works fine.  The above is the printed result of the source command on the form that I build and then eval.  When I eval in the repl, it gives me (s).  When I eval in the code, it does not.  Any ideas?
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Lutz

#1
Works fine for me:


#!/usr/bin/newlisp

(set 'result (match '((square ?)) '((square s))))
(println "=>" result)

(exit)


and when I run it:


~> ./match
=>(s)
>


also tried inside a user defined function, and its fine. Can you isolate the problem in a small file?

Jeff

#2
Ok, here is the block of code that builds the list and then matches against it:


(setq *methods* '())

(define-macro (define-method)
  (letex ((mtd (args 0 0))
 (arglist (rest (args 0)))
 (body (cons 'begin (rest (args)))))
(push (list 'mtd 'arglist 'body) *methods* -1)
(unless (lambda? 'm)
(set 'mtd (curry call-method 'mtd)))))

(define (arg-match arg-list , (lst '()))
  (dolist (elt arg-list)
(if (and (list? elt) (context? (eval (first elt))))
(push (list (first elt) '?) lst -1)
(push '? lst -1)))
  lst)

(define (method-lookup mtd-name arglist)
  (catch
   (begin
(dolist (mtd *methods*)
  (let ((matcher (arg-match arglist))
(matchee (nth 1 mtd)))
(println (list 'match matcher matchee))
(if (and (= (first mtd) mtd-name)
 (match matcher matchee)) ;; NOT MATCHING
(throw mtd))))
(throw-error "no matching method found"))))


Here is an example use of define-method (also showing another macro, define-class, that effectively does the same thing as the (cons (context) ...) FOOP constructor:


(define-class square ()
  (len nil)
  (wid nil))

(define-class cube (square)
  (hgt nil))

(define-method (test (square s))
  (+ (slot-value s 'len) (slot-value s 'wid)))

(define-method (test (cube s))
  (+ (slot-value s 'len) (slot-value s 'wid) (slot-value s 'hgt)))


The idea is that define-method stores a function in *methods*.  Each method that is defined for the same name has a signature which is used to look it up when the wrapper function is called.  I.e., if test is called with s as an instance of square, it matches against the first definition.  If it is called with a cube, it matches the second.  The form (square s) in the argument list means that it is defined for squares and the variable will be s inside the function.  Eventually, I'll add support for default values, commas, etc.



The signature is matched against by constructing a match list using the arguments called.  Each argument is tested to see if it's a list and the first item is a context, which is good enough for me to assume it is an instance of a class.  If it is, it is paired as (context-symbol '?) and appended to the overall match string.



That match string is then matched against the method signature.



PS this is exploratory code; don't expect good performance out of it :).
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Jeff

#3
I found a clue.  If I change arg-match to use (list '? '?) or (list 'square '?) instead of (list (first elt) '?) I get a match.  Does that mean that the symbol representing a context cannot be used in match?
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Lutz

#4
A context and a context symbol look the same but are different things:


> (context 'CTX) (context MAIN)
> (list CTX)
(CTX)
> (= (list CTX) '(CTX))
nil
> (= (list 'CTX) '(CTX))
true
 

> (symbol? (first (list CTX)))
nil
> (symbol? (first '(CTX)))
true
> (context? (first (list CTX)))
true

 
> (context? (first '(CTX)))
nil
> (context? (eval (first '(CTX))))
true
>


So depending how the list is constructed, you are looking at the symbol of a  context or the context itself, both appear to be the same visually.

Jeff

#5
I tried doing applying quote to the context in arg-match, but that didn't work either (to quote the context symbol).  Any idea how I can get this to work?  The first argument to match is constructed in arg-match.
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Lutz

#6
we posted at the same time ;-), read my previous post. You could do (eval (first elt)) to compare contexts.

Jeff

#7
Lutz,



Evaluating the context does not work either.  I need to not only match the contexts but also the other arguments as well (although applying the method is not written yet).  I finally got it to work with this arg-match:


(define (arg-match arg-list , (lst '()))
  (map (lambda (elt)
(if (and (list? elt) (context? (eval (first elt))))
(list (sym (name (first elt))) '?) '?))
  arg-list))


...and matching against the whole method entry, using (match (list mtd-name (arg-match arglist) '?) mtd), which just gives met the body of the function (although it needs to be converted to a lambda).
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code