[racket] matching behavior in dispatch-rules

From: Matthew Butterick (mb at mbtype.com)
Date: Sat Jan 18 23:59:29 EST 2014

If you run this code:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#lang racket
(require web-server/dispatch
         web-server/http/request-structs
         net/url)

(define (url->request u)
  (make-request #"GET" (string->url u) empty
                (delay empty) #f "1.2.3.4" 80 "4.3.2.1"))

(define-values (test-dispatch sum-url)
  (dispatch-rules
   [((? string?) "foo" (? string?)) test-route]
   [((? string?) (? (λ(x) (equal? x "bar"))) (? string?)) test-route]))

(define (test-route req . args)
  (displayln (format "args = ~v" args)))

(test-dispatch (url->request "http://url.com/first-string/foo/second-string.html"))
(test-dispatch (url->request "http://url.com/first-string/bar/second-string.html"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

You'll get this:

args = '("first-string" "second-string.html")
args = '("first-string" "bar" "second-string.html")


Whereas if you use these patterns with regular match, like so:

(match (list "first-string" "foo" "second-string.html")
    [(and matched (list (? string?) "foo" (? string?))) matched])

(match (list "first-string" "bar" "second-string.html")
    [(and matched (list (? string?) (? (λ(x) (equal? x "bar"))) (? string?))) matched])

You'll get:

'("first-string" "foo" "second-string.html")
'("first-string" "bar" "second-string.html")


Thus my question: why doesn't the literal "foo" in the first pattern under dispatch-rules become one of the matched items, as it does with regular match?



Posted on the users mailing list.