Hacker News new | past | comments | ask | show | jobs | submit login

> (You can’t, unless CASE is itself optimized to a jump table, which it usually isn’t.)

That's surprising. Even the brain-dead compiler in my TXR Lisp (a dialect that has some things in common with Common Lisp) does it.

  1> (disassemble 
        (compile-toplevel
          '(caseql x (1 'a) (2 'b) (3 'c) ((4 5 6) 'd) (7 'e) (8 'f) (9 'g))))
  ** warning: (expr-1:3) unbound variable x
  data:
      0: #:nohit
      1: a
      2: b
      3: c
      4: d
      5: e
      6: f
      7: g
  syms:
      0: x
      1: integerp
      2: <=
      3: sys:b-
  code:
      0: 04020002 frame 2 2
      1: A0800000 getlx v00000 0
      2: 30810400 movsr v00001 d000
      3: 24010003 gcall t003 1 v00000
      4: 08000001
      5: 48000026 if t003 38
      6: 00000003
      7: 38050004 movrsi t004 1
      8: 38250005 movrsi t005 9
      9: 24030003 gcall t003 2 t004 v00000 t005
     10: 00040002
     11: 00050800
     12: 48000026 if t003 38
     13: 00000003
     14: 38050005 movrsi t005 1
     15: 24020004 gcall t004 3 v00000 t005
     16: 08000003
     17: 00000005
     18: 54090004 swtch t004 24 26 28 30 30 30 32 34 36
     19: 001A0018
     20: 001E001C
     21: 001E001E
     22: 00220020
     23: 00000024
     24: 30810401 movsr v00001 d001
     25: 44000025 jmp 37
     26: 30810402 movsr v00001 d002
     27: 44000025 jmp 37
     28: 30810403 movsr v00001 d003
     29: 44000025 jmp 37
     30: 30810404 movsr v00001 d004
     31: 44000025 jmp 37
     32: 30810405 movsr v00001 d005
     33: 44000025 jmp 37
     34: 30810406 movsr v00001 d006
     35: 44000025 jmp 37
     36: 30810407 movsr v00001 d007
     37: 30030801 movsr t003 v00001
     38: 4C00002A ifq v00001 d000 42
     39: 08010400
     40: 30020000 movsr t002 nil
     41: 4400002B jmp 43
     42: 30020801 movsr t002 v00001
     43: 10000002 end t002
     44: 10000002 end t002
  instruction count:
     32
  #<sys:vm-desc: 8522ca8>

And, oh, the work is done by ... the case macro!

  2> (macroexpand '(caseql x (1 'a) (2 'b) (3 'c) ((4 5 6) 'd) (7 'e) (8 'f) (9 'g)))
  (let ((#:test-0034
         x)
        (#:swres-0036
         '#:nohit))
    (and (integerp #:test-0034)
      (<= 1 #:test-0034
          9)
      (set #:swres-0036
        (sys:switch (- #:test-0034
                       1)
          #(('a) ('b) ('c)
            ('d) ('d) ('d)
            ('e) ('f) ('g)))))
    (if (eq #:swres-0036
            '#:nohit)
      (progn) #:swres-0036))
The sys:swtch special form is then spun into the jump table code.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: