[racket] Splicing nested syntax clauses

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Sat Jun 28 09:22:05 EDT 2014

Here's another approach:

#lang racket/base
(require (for-syntax racket/base)
         web-server/dispatch)

(begin-for-syntax
  (define-syntax-rule (in-stx-list l)
    (in-list (syntax->list l))))

(define-syntax (nested-dispatch-rules stx)
  (syntax-case stx ()
    [(_ [(prefix ...) [(suffix ...) handler] ...] ...)
     (with-syntax
         ([((clause ...) ...)
           (for/list ([pre (in-stx-list #'((prefix ...) ...))]
                      [post (in-stx-list #'(([(suffix ...) handler] ...) ...))])
             (with-syntax
                 ([(prefix ...) pre]
                  [([(suffix ...) handler] ...) post])
               #'([(prefix ... suffix ...) handler] ...)))])
       (syntax/loc stx
         (dispatch-rules clause ... ...)))]))

(module+ test
  (define (handler-a req x) "A")
  (define (handler-b req x) "B")
  (define (handler-c req x) "C")
  (define (handler-d req x) "D")

  (define-values (dispatch dispatch-url)
    (nested-dispatch-rules
     [("page-a")
      [("handler-a" (integer-arg)) handler-a]
      [("handler-b" (integer-arg)) handler-b]]
     [("page-b")
      [("handler-c" (integer-arg)) handler-c]
      [("handler-d" (integer-arg)) handler-d]]))

  (require rackunit)
  (check-equal? (dispatch-url handler-a 0) "/page-a/handler-a/0")
  (check-equal? (dispatch-url handler-b 1) "/page-a/handler-b/1")
  (check-equal? (dispatch-url handler-c 2) "/page-b/handler-c/2")
  (check-equal? (dispatch-url handler-d 3) "/page-b/handler-d/3"))

On Fri, Jun 27, 2014 at 1:47 PM, Jack Firth <jackhfirth at gmail.com> wrote:
> I'm working with some servlet dispatching code and I want to be able to use
> dispatch-rules to generate the url to response mappings, but I want to be
> able to group related handlers to subpages. Under dispatch-rules, that looks
> something like this:
>
> (dispatch-rules
>     [("page-a" "handler-a" (integer-arg)) handler-a]
>     [("page-a" "handler-b" (integer-arg)) handler-b]
>     [("page-b" "handler-c" (integer-arg)) handler-c]
>     [("page-b" "handler-d" (integer-arg)) handler-d])
>
> What I want is to be able to specify a tree structure of some sort like
> this:
>
> (my-dispatch-rules
>     [(my-dispatch-rules "page-a"
>         [("handler-a" (integer-arg)) handler-a)]
>         [("handler-b" (integer-arg)) handler-b)]
>     [(my-dispatch-rules "page-b"
>         [("handler-c" (integer-arg)) handler-c)]
>         [("handler-d" (integer-arg)) handler-d)])
>
> And have that expand, placing the page-a and page-b bits in the appropriate
> areas. From what I understand of macros, the appropriate way to do this is
> with quasiquoting and splicing unquotes, but I can't seem to figure out
> using splicing with syntax-case, and the various tutorials and documentation
> I've looked at haven't helped me really wrap my head around the specifics.
> If someone could point me towards enlightenment, that would be much
> appreciated.
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>



-- 
Jay McCarthy
http://jeapostrophe.github.io

           "Wherefore, be not weary in well-doing,
      for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
                          - D&C 64:33

Posted on the users mailing list.