[racket-dev] [plt-scheme] Bug or misuse? match-expander ids not properly working (patch)

From: J. Ian Johnson (ianj at ccs.neu.edu)
Date: Fri May 4 14:27:57 EDT 2012

That behavior would be really spooky to me. I would expect binding positions to not depend on any environmental information. Perhaps have an (id _) form that would allow putting your special identifiers there.

-Ian

----- Original Message -----
From: "Eli Barzilay" <eli at barzilay.org>
To: "Sam Tobin-Hochstadt" <samth at ccs.neu.edu>, "Madoka Machitani" <madokama at gmail.com>
Cc: dev at racket-lang.org
Sent: Friday, May 4, 2012 2:16:07 PM GMT -05:00 US/Canada Eastern
Subject: Re: [racket-dev] [plt-scheme] Bug or misuse? match-expander ids not properly working	(patch)

This is an *ancient* patch suggestion that I dug up in my quest for
smaller inbox...  (It's really old, so won't work as is.)

It makes it possible to define identifier syntaxes as match expanders,
and that would probably make it possible to also address the
relatively common complaint about not having a `null' match pattern
that does the obvious thing.  Last time we talked about this (= me &
Sam) I think that there was some point about identifiers being
unambiguously used as patterns -- but I don't see a problem with the
following approach of specifying specific names as patterns.  If the
builtin identifier patterns are kept to a minimum (for example, only
`null', `true' and `false'), then I don't think that this will be
confusing in any way.


On November 24th 2009, Madoka Machitani wrote:
> Hi!
> 
> I've encountered a problem while implementing red-black trees:
> 
> (define-struct tree
>   (color key value left right))
> 
> (define empty (make-tree 'black #f #f #f #f))
> (define (empty? t) (eq? t empty))
> 
> 
> To ease access with the pattern match syntax, I wrote match expanders
> for trees as follows:
> 
> (define-match-expander T
>   (lambda (stx)
>     (syntax-case stx ()
>       ((T c l (k v) r)
>        (syntax/loc stx
>          (struct tree (c k v l r))))))
>   (lambda (stx)
>     (syntax-case stx ()
>       ((T c l (k v) r)
>        (syntax/loc stx
>          (make-tree c k v l r))))))
> 
> (define-match-expander R
>   (lambda (stx)
>     (syntax-case stx ()
>       (R (syntax 'red))))
>   (lambda (stx)
>     (syntax-case stx ()
>       (R (syntax 'red)))))
> 
> (define-match-expander B
>   (lambda (stx)
>     (syntax-case stx ()
>       (B (syntax 'black))))
>   (lambda (stx)
>     (syntax-case stx ()
>       (B (syntax 'black)))))
> 
> (define-match-expander E
>   (lambda (stx)
>     (syntax-case stx ()
>       (E (syntax/loc stx (? empty?)))))
>   (lambda (stx)
>     (syntax-case stx ()
>       (E (syntax/loc stx empty)))))
> 
> 
> which should enable one to construct and match trees a la Haskell:
> 
> (match (T B E ('a 1) E)
>   ((T B E (k v) E)
>    "This is a black tree with both subtrees empty."))
> 
> 
> However, this doesn't work as I expected.  I.e., "B" and "E" in the
> pattern clause above are treated as plain variables, thus matching
> anything.  Seemingly match expander ids in pattern match clauses take
> effect only when used in "application" form.
> 
> So I wrote a patch.
> 
> The first portion is irrelevant to this particular issue, but fixes
> a bug which inecessarily converts unnamed let syntax to a named one.
> 
> The second part is required for the third one to work when only
> expander ids are used in match-let etc bindings.
> 
> I hope it's accepted.
> 
> regards,
> 
> diff -ur orig/define-forms.ss ./define-forms.ss
> --- orig/define-forms.ss	2009-09-17 12:09:40.000000000 +0900
> +++ ./define-forms.ss	2009-11-25 13:23:40.000000000 +0900
> @@ -72,7 +72,7 @@
>           ;; optimize the all-variable case
>           [(_ ([pat exp]...) body ...)
>            (andmap pattern-var? (syntax->list #'(pat ...)))
> -          (syntax/loc stx (let name ([pat exp] ...) body ...))]
> +          (syntax/loc stx (let ([pat exp] ...) body ...))]
>           [(_ name ([pat exp]...) body ...)
>            (and (identifier? (syntax name))
>                 (andmap pattern-var? (syntax->list #'(pat ...))))
> diff -ur orig/parse-helper.ss ./parse-helper.ss
> --- orig/parse-helper.ss	2009-09-17 12:09:40.000000000 +0900
> +++ ./parse-helper.ss	2009-11-25 13:44:34.000000000 +0900
> @@ -141,10 +141,17 @@
>  (define (match:syntax-err stx msg)
>    (raise-syntax-error #f msg stx))
> 
> +;; match-var? : syntax -> bool
> +;; is p an identifier representing a pattern transformer?
> +(define (match-var? p)
> +  (match-expander?
> +   (syntax-local-value ((syntax-local-certifier) p)
> +		       (lambda () #f))))
> +
>  ;; pattern-var? : syntax -> bool
>  ;; is p an identifier representing a pattern variable?
>  (define (pattern-var? p)
> -  (and (identifier? p) (not (ddk? p))))
> +  (and (identifier? p) (not (ddk? p)) (not (match-var? p))))
> 
>  ;; ddk? : syntax -> number or boolean
>  ;; if #f is returned, was not a ddk identifier
> diff -ur orig/parse.ss ./parse.ss
> --- orig/parse.ss	2009-09-17 12:09:40.000000000 +0900
> +++ ./parse.ss	2009-11-25 01:44:44.000000000 +0900
> @@ -32,6 +32,13 @@
>       (match-expander-transform
>        parse/cert cert #'expander stx match-expander-match-xform
>        "This expander only works with the legacy match syntax")]
> +    [expander
> +     (and (identifier? #'expander)
> +          (match-expander? (syntax-local-value (cert #'expander)
> +                                               (lambda () #f))))
> +     (match-expander-transform
> +      parse/cert cert #'expander stx match-expander-match-xform
> +      "This expander only works with the legacy match syntax")]
>      [(var v)
>       (identifier? #'v)
>       (make-Var #'v)]
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!
_________________________
  Racket Developers list:
  http://lists.racket-lang.org/dev

Posted on the dev mailing list.