[racket] Any way to get "true" quasiquote behavior in match form?

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Sun Mar 11 00:56:04 EST 2012

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/


Posted on the users mailing list.