define-match-expander
Asked Answered
A

2

7

about the define-match-expansion, there are rare materials and example codes to illustrate the concepts. I am having a hard time to "decode" what the documentation says:

(define-match-expander id proc-expr)
(define-match-expander id proc-expr proc-expr)

Binds id to a match expander.

The first proc-expr subexpression must evaluate to a transformer that produces a pat for match. Whenever id appears as the beginning of a pattern, this transformer is given, at expansion time, a syntax object corresponding to the entire pattern (including id). The pattern is the replaced with the result of the transformer.

A transformer produced by a second proc-expr subexpression is used when id is used in an expression context. Using the second proc-expr, id can be given meaning both inside and outside patterns.

Can anyone give some example codes to illustrate the two usages of the define-match-expander here?

Antiscorbutic answered 27/2, 2011 at 21:22 Comment(0)
C
6

The idea behind match-expander is that you can extend the 'match' form to handle new pattern forms of your own design.

So, here's a (somewhat pointless) example that defines an "aba" match form that matches patterns of one thing followed by another thing followed by the first thing again (hence, "aba"):

#lang racket

(define-match-expander aba
  (lambda (stx)
    (syntax-case stx ()
      [(_ a b) #'(list a b a)])))

(match '(3 4 3)
  [(aba x y) (printf "x = ~a, y = ~a" x y)])

The second form allows you to add a separate expansion to be used outside of match patterns, like this:

#lang racket

(define-match-expander aba
  (lambda (stx)
    (syntax-case stx ()
      [(_ a b) #'(list a b a)]))
  (lambda (stx)
    #'(error "please don't use aba outside of patterns.")))

(match '(3 4 3)
  [(aba x y) (printf "x = ~a, y = ~a\n" x y)])

(aba x y)

Caveat: whuffo the extra pair of parens around the pattern? Not sure, sorry.

Camphor answered 27/2, 2011 at 21:50 Comment(4)
so your example shows that 1. whether '(3 4 3) matches the form as aba, the new pattern. 2. can you explain how syntax-case works? I don't see anywhere that can check a b a form. Or say: I guess x is bind to 3, y is bind to 4, but where shows '(3 4 3) satisfied the a b a pattern?Antiscorbutic
or my other understanding is that: the define-match-expander, defines a new pattern form to be used in match. The syntax-case, #'(list a b a) is in tail position, which will be the return expression, which is used to match '(3 4 3)? if it matches, the x will be bind to 3, and y to 4? Are these the things going on for the example code?Antiscorbutic
Yes, that sounds like a plausible summary. Apologies for my use of syntax-case rather than the simpler syntax-rules; I'm just used to using syntax-case.Camphor
Well, glad to see Yes anyway. Your example helps! (I am just feeling I am not quite following the documentations, I would prefer examples)Antiscorbutic
H
2

This is a really old question, but I'd like to add the example using "syntax-rules" for the same "aba" pattern:

(define-match-expander aba
  (syntax-rules ()
    [(aba a b) (list a b a)]))

(match '(3 4 3)
  [(aba x y) (printf "x = ~a, y = ~a" x y)])

Left-hand side (aba a b) is the thing going in the match, the right-hand side (list a b a) is the substitution.

(match '(3 4 3)
  [(aba x y) (printf "x = ~a, y = ~a" x y)])

is replaced by

(match '(3 4 3)
  [(list x y x) (printf "x = ~a, y = ~a" x y)])

The nice part is that the new matcher works for ALL "match-whatever" functions, like:

(match-define (aba x y) (list 1 2 1))
(printf "x = ~a, y = ~a" x y
Headboard answered 7/1, 2018 at 19:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.