Ah, yes, I didn't see Carl's solution, which is pleasantly concise and particularly nice because of the single case. But I still think the point about fall-through is important to the performance model of `switch' -- it's what Duff's Device relies on, for example.
If you care about constructs like `switch', of course. ;) Dave On Oct 9, 2010, at 4:50 PM, Jay McCarthy wrote: > This looks a lot like Carl's (and my modification of it.) > > Jay > > On Sat, Oct 9, 2010 at 5:46 PM, David Herman <dher...@ccs.neu.edu> wrote: >> I thought about the "am I falling through?" approach you've been taking, but >> the problem is that it keeps having to recompute the same test. In C-like >> languages, one of the benefits of `switch' [1] is that fall-through is >> expected to either be a literal "execute the next instruction in the PC" or >> at least a jump to a fixed address. So I prefer an approach that sets up a >> basic-block-like structure, like so: >> >> +-------+ >> | test1 | >> +-------+ ....> +------+ >> . | rhs1 | >> . +------+ >> v . >> +-------+ . >> | test2 | v >> +-------+ ....> +------+ >> . | rhs2 | >> . +------+ >> v . >> +-------+ . >> | test3 | v >> +-------+ ....> +------+ >> . | rhs3 | >> . +------+ >> . . >> . . >> >> If each of these blocks is compiled as a local thunk, I'd expect a decent >> (not necessarily brilliant) Scheme compiler to be able to turn the function >> call at the end of each rhs_i block into a jump to a static address, and >> possibly even reorder the basic blocks to make some of them jump-less. With >> modern branch-prediction, the latter may be unnecessary. >> >> With that, here's my solution: >> >> #lang racket >> >> (require racket/stxparam) >> >> (define-syntax-parameter break >> (lambda (stx) >> (raise-syntax-error 'break "used outside of cas-cad-e case" stx))) >> >> (define-syntax (cas-cad-e stx) >> (syntax-case stx () >> [(_ disc) >> #'(void)] >> [(_ disc [lhs rhs ...] ... [last-lhs last-rhs ...]) >> (let ([test-ids (generate-temporaries (syntax->list #'(lhs ...)))] >> [consequent-ids (generate-temporaries (syntax->list #'(lhs ...)))] >> [last-test-id (car (generate-temporaries (list #'last-lhs)))] >> [last-consequent-id (car (generate-temporaries (list >> #'last-lhs)))]) >> (with-syntax ([(test ...) test-ids] >> [(consequent ...) consequent-ids] >> [last-test last-test-id] >> [last-consequent last-consequent-id]) >> (with-syntax ([(next-test ...) (append (cdr test-ids) (list >> last-test-id))] >> [(next-consequent ...) (append (cdr consequent-ids) >> (list last-consequent-id))]) >> (with-syntax ([test0 (if (null? test-ids) last-test-id (car >> test-ids))]) >> #'(let ([disc-v disc]) >> (let/ec k >> (syntax-parameterize ([break (syntax-rules () >> [(_ v) >> (k v)])]) >> (define (test) >> (case disc-v >> [lhs (consequent)] >> [else (next-test)])) >> ... >> (define (consequent) >> rhs ... >> (next-consequent)) >> ... >> (define (last-test) >> (case disc-v >> [last-lhs (last-consequent)])) >> (define (last-consequent) >> last-rhs ...) >> (test0))))))))])) >> >> Dave >> >> [1] Please do not construe this as tacit approval of the `switch' form. Ick. >> >> On Oct 9, 2010, at 6:13 AM, Jay McCarthy wrote: >> >>> I don't really like have the call-with-values and apply there, so >>> here's another version. It makes the macro a bit longer with the >>> additional case and has the pattern duplicated once, but it seems >>> worth it: >>> >>> (define-syntax cas-cad-e >>> (syntax-rules () >>> [(_ e) (begin e (void))] >>> [(_ e [(n ...) code ...] ... [(n_l ...) code_l ...]) >>> (let/ec esc >>> (syntax-parameterize >>> ([break (make-rename-transformer #'esc)]) >>> (let* ([tmp e] >>> [earlier? #f] >>> [earlier? >>> (if (or earlier? (equal? tmp n) ...) >>> (begin code ... #t) >>> earlier?)] >>> ...) >>> (when (or earlier? (equal? tmp n_l) ...) >>> code_l ...))))])) >>> >>> Regarding Shriram's bug. The only thing that occurs to me is that >>> you'd want eqv? and a ' on the ns, to be more like case. >>> >>> Jay >>> >>> On Fri, Oct 8, 2010 at 10:39 PM, Jay McCarthy <jay.mccar...@gmail.com> >>> wrote: >>>> You got me >>>> >>>> Sent from my iPhone >>>> >>>> On Oct 8, 2010, at 10:33 PM, Eli Barzilay <e...@barzilay.org> wrote: >>>> >>>>> 8 minutes ago, Jay McCarthy wrote: >>>>>> Alright, here's the version with no mutation: >>>>> >>>>> (cas-cad-e 1 [(1) (values 1 2 3)]) >>>>> >>>>> In other words: >>>>> >>>>> (define-syntax-rule (cas-cad-e e [(n ...) code ...] ...) >>>>> (let/ec esc >>>>> (syntax-parameterize ([break (make-rename-transformer #'esc)]) >>>>> (let*-values ([(tmp) e] >>>>> [(earlier? ret) (values #f (void))] >>>>> [(earlier? ret) >>>>> (if (or earlier? (equal? tmp n) ...) >>>>> (values #t (call-with-values (lambda () code ...) >>>>> list)) >>>>> (values earlier? ret))] >>>>> ...) >>>>> (apply values ret))))) >>>>> >>>>> -- >>>>> ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: >>>>> http://barzilay.org/ Maze is Life! >>>> >>> >>> >>> >>> -- >>> Jay McCarthy <j...@cs.byu.edu> >>> Assistant Professor / Brigham Young University >>> http://teammccarthy.org/jay >>> >>> "The glory of God is Intelligence" - D&C 93 >>> _________________________________________________ >>> For list-related administrative tasks: >>> http://lists.racket-lang.org/listinfo/users >> >> > > > > -- > Jay McCarthy <j...@cs.byu.edu> > Assistant Professor / Brigham Young University > http://teammccarthy.org/jay > > "The glory of God is Intelligence" - D&C 93 _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users