[racket] Any way to get "true" quasiquote behavior in match form?
rob cook wrote at 03/10/2012 08:46 PM:
> (eval `(match ',(car z) (,@(cdr words) #t) (_ #f)))
>
> gets me what I need, but the overhead (and ugliness) of using eval is
> killing me.
Separate from a ``backquote''-like feature being added to "match", or
writing your own data-driven pattern matcher... I hate to say this,
since I usually have to advise people *not* to use "eval", but... rather
than use "eval" to *perform a single match*, you can use "eval" to *make
a procedure that performs the match*...
#lang racket/base
(define some-matcher-namespace
;; TODO: Set up this namespace better.
(let ((ns (make-base-namespace)))
(parameterize ((current-namespace ns))
(namespace-require 'racket/match))
ns))
(define (make-some-matcher pattern-list)
(eval `(let ((<make-some-matcher>
(lambda (val)
(match val
(, at pattern-list #t)
(_ #f)))))
<make-some-matcher>)
some-matcher-namespace))
;; Tests:
(require (planet neil/overeasy))
(define my-first-matcher (make-some-matcher '((list "a" "b" "c"))))
(test (my-first-matcher '("a" "b" "c")) #t)
(test (my-first-matcher '("a" "b")) #f)
(test (my-first-matcher '("a" "b" "c" "d")) #f)
(test (my-first-matcher 42) #f)
(test (format "~S" my-first-matcher) "#<procedure:<make-some-matcher>>")
;; Performance:
(require (planet neil/shootout))
(shootout (my-first-matcher '("a" "b" "c"))
(my-first-matcher 42)
#:repeat 1000000)
Note that this program includes performing 2 million "match"
operations. Running this program (without compiling) on my 5-year-old
laptop just now took 2.092 seconds of wall clock time, as measured from
the OS command line by "time racket foo.rkt". The 2 million "match"
operations themselves take about 0.2 seconds. I suspect that one could
optimize this further.
"eval" is usually not the right thing to use, but hopefully these
performance numbers are good enough for your project to move forward.
Neil V.
--
http://www.neilvandyke.org/