[racket] How can I use the results of a pattern match to produce a value in a match-expander?

From: Sam Tobin-Hochstadt (samth at cs.indiana.edu)
Date: Fri Jan 16 18:17:47 EST 2015

I also answered on SO, but you just want to do more in the `app` pattern:

#lang racket

(struct foo (a b c) #:transparent)

(define-match-expander foo-string
  (λ (stx)
    (syntax-case stx ()
      [(_ result)
       #'(app (λ (v) (apply (λ (_ a b c) (foo a b c))
                            (regexp-match #px"^(.+)\\s(.+)\\s(.+)$" v)))
              result)])))

(define (foo-from-str str)
  (match str
    [(foo-string value) value]
    [_ #f]))

(foo-from-str "1 2 3")

Sam

On Fri Jan 16 2015 at 4:42:56 PM Alexis King <lexi.lambda at gmail.com> wrote:

> Yes, chandler already suggested something like that on #racket. I didn’t
> think of that, but it should work. It’d be nice if there were a cleaner way
> to do it, but if you want to post that as an answer on SO for the imaginary
> internet points, I’d accept it.
>
> On Jan 16, 2015, at 13:38, Alexander D. Knauth <alexander at knauth.org>
> wrote:
>
> Would this work for what you want?
> #lang racket
> (require rackunit)
> (struct foo (a b c))
> (define-match-expander foo-string
>   (λ (stx)
>     (syntax-case stx ()
>       [(_ result)
>        #'(app (λ (v)
>                 (match v
>                   [(pregexp #px"^(.+)\\s(.+)\\s(.+)$" (list _ a b c))
>                    (foo a b c)]
>                   [_ #f]))
>               (? foo? result))])))
> (define (foo-from-str str)
>   (match str
>     [(foo-string value) value]
>     [_ #f]))
>
> (check-match (foo-from-str "1 2 3") (foo "1" "2" "3"))
>
>
> On Jan 16, 2015, at 4:24 PM, Alexis King <lexi.lambda at gmail.com> wrote:
>
> I just posted a question on Stack Overflow asking about using racket/match
> <http://stackoverflow.com/q/27992566/465378>. Since I’m not sure how
> active the racket tag is on SO, I figured I’d also post it here. For those
> who don’t want to look at the SO question, here’s the question’s contents.
>
> In a racket/match pattern, I want to match some values, then create a
> struct that wraps them. For example, take the following (contrived) code:
>
> (struct foo (a b c))
> (define (foo-from-string str)
>   (match str
>     [(pregexp #px"^(.+)\\s(.+)\\s(.+)$" a b c)
>      (foo a b c)]
>     [_ #f]))
>
> I frequently find myself matching this list of three elements in other
> patterns, then creating a struct from it. Therefore, I wanted to simplify
> this by writing a custom match expander. Ideally, it would work like this:
>
> (struct foo (a b c))
> (define (foo-from-str str)
>   (match str
>     [(foo-string value) value]
>     [_ #f]))
>
> That is, it should automatically match a string that satisfies the regex,
> then store the values into a foo struct on success and bind it to value.
> I tried writing something like the following to implement this:
>
> (define-match-expander foo-string
>   (λ (stx)
>     (syntax-case stx ()
>       [(_ result)
>        #'(and (pregexp #px"^(.+)\\s(.+)\\s(.+)$" a b c)
>               (app (λ (v) (foo a b c)) result))])))
>
> Unfortunately, this fails because a, b, and c, are unbound when the
> function passed to the app pattern gets called. Is there any way to
> implement such a match expander so that it can perform some arbitrary
> procedure on the matched values?
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users
>
>
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20150116/03e0bca0/attachment.html>

Posted on the users mailing list.