Some stuff about "case".

47 views
Skip to first unread message

Christopher Lemmer Webber

unread,
Jun 1, 2020, 2:54:01 PM6/1/20
to racket users
As I started typing this email and looking into the definition of case,
I realized my assumptions are wrong.

What I needed: something like case which dispatches on symbols, except
not auto-quoting the arguments... I needed to evaluate them from the
lexical environment. So:

(let ([x 'foo])
(caseish 'foo
[(x) 'got-foo]
[('x) 'got-quote-x])) ; => 'got-foo

I figured: case is fast, and I'm pretty sure semi-magical... my
intuitive sense was that it did some smart things on a compiler level
that would probably be anything I'd hand-code (which would either use an
alist or an immutable hashtable). So I started writing up an email
asking if such a thing worked... then I remembered, this is a ~lisp,
jumping straight to definition is part of the scene... so I did that.

I... was wrong! From the case macro:

;; Symbol and "other" dispatch is either sequential or
;; hash-table-based, depending on how many constants we
;; have. Assume that `alist' does not map anything to `#f'.
(define (dispatch-hashable tmp-stx alist make-hashX else-exp)
(if (< (length alist) *hash-threshold*)
#`(case/sequential #,tmp-stx
#,@(map (λ (x)
#`[(#,(car x)) #,(cdr x)])
alist)
[else #,else-exp])
(let ([tbl (make-hashX alist)])
(if (literal-expression? else-exp)
#`(hash-ref #,tbl #,tmp-stx (lambda () #,else-exp))
#`(or (hash-ref #,tbl #,tmp-stx (lambda () #f))
#,else-exp)))))

Am I reading that right? Here I was assuming writing something like
case was for cool kids and I'd never pull such a thing off right.

But... now it looks like, oh, it's actually just using an alist or an
immutable hashtable... same as I would.

So I almost trashed this email, but thought I'd send it anyway because
a) either maybe it's interesting to someone or b) actually maybe I'm
misreading and case really is smarter / more performant and I'm just
missing it...!

- Chris

Christopher Lemmer Webber

unread,
Jun 1, 2020, 2:59:18 PM6/1/20
to racket users
Except maybe for one thing: I wonder if the version of case defined here
is written in such a way that is smart in that it never has to make said
hash table / alist more than once, at compile time. I'm guessing so?

Jens Axel Søgaard

unread,
Jun 1, 2020, 3:52:42 PM6/1/20
to Christopher Lemmer Webber, racket users
Den man. 1. jun. 2020 kl. 20.53 skrev Christopher Lemmer Webber <cwe...@dustycloud.org>:
As I started typing this email and looking into the definition of case,
I realized my assumptions are wrong.

What I needed: something like case which dispatches on symbols, except
not auto-quoting the arguments... I needed to evaluate them from the
lexical environment.  So:

  (let ([x 'foo])
    (caseish 'foo
      [(x) 'got-foo]
      [('x) 'got-quote-x]))  ; => 'got-foo

 
I figured: case is fast, and I'm pretty sure semi-magical... my
intuitive sense was that it did some smart things on a compiler level
that would probably be anything I'd hand-code (which would either use an
alist or an immutable hashtable).  

I think `case` were more important before `match` arrived.
If you want to see how `case` can be implemented without hash-tables, look at
William D Clinger's paper:

http://scheme2006.cs.uchicago.edu/07-clinger.pdf

/Jens Axel
 

Jon Zeppieri

unread,
Jun 1, 2020, 3:55:36 PM6/1/20
to Jens Axel Søgaard, Christopher Lemmer Webber, racket users
The Racket implementation of case is based on Clinger's paper. And
Clinger's approach does, in fact, use hash tables, except that in the
Larceny implementation, the hash table fetch is open-coded by case
(IIRC), which is not the case in Racket (unless it gets inlined by the
compiler in the CS version, I suppose, though I don't know if that's
actually possible).

- Jon

Jack Firth

unread,
Jun 3, 2020, 4:06:16 AM6/3/20
to Racket Users
Isn't that just match with the == pattern?


(let ([x 'foo])
  (match 'foo
    [(== x) 'got-foo]
    ['x 'got-quote-x])) ; => 'got-foo
Reply all
Reply to author
Forward
0 new messages