[plt-scheme] match expander weirdness

From: Dimitris Vyzovitis (vyzo at media.mit.edu)
Date: Sat Feb 24 12:56:01 EST 2007

Hi,

I am experiencing a weird problem with (renamed) match expanders. The
creatures in reference deconstruct structs that come from different
modules, but have the same name in their respective modules.

Example:
(module sa mzscheme
  (require (lib "plt-match.ss"))

  (define-struct foo (x y z) #f)
  (define-match-expander Foo
    #:plt-match
    (lambda (stx)
      (syntax-case stx ()
        ((_Foo field ...)
         #'(? foo? (app struct->vector (vector _ field ...))))))
    #:expression
    (lambda (stx)
      (syntax-case stx ()
        ((_Foo field ...)
         #'(make-foo field ...)))))

  (define-match-expander Foo2
    #:plt-match
    (lambda (stx)
      (syntax-case stx ()
        ((_Foo2 field ...)
         #'(struct foo (field ...))))))

  (provide (all-defined))
)

Now, let's define a second module, that has a foo with two fields instead
of three:
(module sb mzscheme
  (require (lib "plt-match.ss"))

  (define-struct foo (x y) #f)
  (define-match-expander Foo
    #:plt-match
    (lambda (stx)
      (syntax-case stx ()
        ((_Foo field ...)
         #'(? foo? (app struct->vector (vector _ field ...))))))
    #:expression
    (lambda (stx)
      (syntax-case stx ()
        ((_Foo field ...)
         #'(make-foo field ...)))))

  (define-match-expander Foo2
    #:plt-match
    (lambda (stx)
      (syntax-case stx ()
        ((_Foo2 field ...)
         #'(struct foo (field ...))))))

  (provide (all-defined))
)

and then:
> (version)
"369.8"
> (require (lib "plt-match.ss"))
> (require (rename "sa.ss" a:Foo Foo))
> (require (rename "sb.ss" b:Foo Foo))
> (match (a:Foo 1 2 3) ((b:Foo _ _) 'b) ((a:Foo _ _ _) 'a))
match: no matching clause for #4(struct:foo 1 2 3)

> (match (a:Foo 1 2 3) ((a:Foo _ _ _) 'a) ((b:Foo _ _) 'b))
a
> (match (b:Foo 1 2) ((a:Foo _ _ _) 'a) ((b:Foo _ _) 'b))
match: no matching clause for #3(struct:foo 1 2)

> (match (b:Foo 1 2) ((b:Foo _ _) 'b) ((a:Foo _ _ _) 'a))
b
> (require (rename "sa.ss" a:Foo2 Foo2))
> (require (rename "sb.ss" b:Foo2 Foo2))
> (match (a:Foo 1 2 3) ((a:Foo2 _ _ _) 'a) ((b:Foo2 _ _) 'b))
Warning: unreachable match clause ((b:Foo2 _ _) (quote b)) in (match
(a:Foo 1 2 3) ((a:Foo2 _ _ _) (quote a)) ((b:Foo2 _ _) (quote b)))
a
> (match (b:Foo 1 2) ((a:Foo2 _ _ _) 'a) ((b:Foo2 _ _) 'b))
Warning: unreachable match clause ((b:Foo2 _ _) (quote b)) in (match
(b:Foo 1 2) ((a:Foo2 _ _ _) (quote a)) ((b:Foo2 _ _) (quote b)))
match: no matching clause for #3(struct:foo 1 2)

It seems that in each case the pattern compiler somehow decides that
the second pattern is unreachable (silently in the struct->vector
decomposition)...

-- vyzo



Posted on the users mailing list.