Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

That is not necessarily true (and I say this as someone who heavily favors C for parsers). An implementation with a JIT will likely be able to optimize away work by noticing that the table of callbacks is empty.

I would be more impressed if the callback table was not empty (and the callbacks actually did something, like increment an integer) and Lisp was still winning.

EDIT: I see others saying that SBCL is AOT, not JIT. If so I'd be very interested to look at the disassembly side-by-side and see an explanation for why SBCL is winning.



SBCL is a compiled Common LISP (even in interpreted mode, it compiles every eval-ed lambda before calling it).

On the other hand there is nothing inherently stopping the optimiser from optimising the resulting code as well or better than GCC or any C compiler. Theoretically it could produce optimal machine code.


Correct me if I'm wrong but I was under the impression that Common Lisp is memory-safe (implying guards like bounds-checks), dynamically typed (implying type checks) and garbage collected (implying GC overhead).


Yep but all these checks don't necessarily need to happen at runtime. A clever enough compiler can optimise all of it (or most of it) at compile time. In general this is a very hard problem but for something static enough (like a simple parser) the compiler can produce code and determine its safety without needing to carry checks on to the runtime.

Note that C code or machine code would also have to perform input checks at runtime when doing http header parsing. A Common Lisp compiler wouldn't theoretically need to produce code performing any more runtime checks than these.


You can also manually turn some checks off. In some Lisp systems, declaring an optimization setting of (safety 0) will turn off a bunch of checks, even ones that the compiler can't statically determine are safe to skip. Of course this should be used very carefully if at all (especially in code that's parsing arbitrary data from the internet!).


SBCL (And other compilers) implement a type inference engine to reduce type checks, and you can also provide your own type declarations, i.e. gradual typing before it had that name.


CL type declarations are cool, but they aren't gradual typing. It doesn't either reject your program if you get them wrong, or dynamically enforce that everyone else lives up to them.


That depends on the optimization levels you select. At it's highest optimization level, there is no type checking and you'd better have your code right.

http://www.sbcl.org/manual/#Declarations-as-Assertions

4.2.1 Declarations as Assertions

The SBCL compiler treats type declarations differently from most other Lisp compilers. Under default compilation policy the compiler doesn’t blindly believe type declarations, but considers them assertions about the program that should be checked: all type declarations that have not been proven to always hold are asserted at runtime.

Remaining bugs in the compiler’s handling of types unfortunately provide some exceptions to this rule, see Implementation Limitations.

CLOS slot types form a notable exception. Types declared using the :type slot option in defclass are asserted if and only if the class was defined in safe code and the slot access location is in safe code as well. This laxness does not pose any internal consistency issues, as the CLOS slot types are not available for the type inferencer, nor do CLOS slot types provide any efficiency benefits.

There are three type checking policies available in SBCL, selectable via optimize declarations.

Full Type Checks

All declarations are considered assertions to be checked at runtime, and all type checks are precise. The default compilation policy provides full type checks.

Used when (or (>= safety 2) (>= safety speed 1)).

Weak Type Checks

Declared types may be simplified into faster to check supertypes: for example, (or (integer -17 -7) (integer 7 17)) is simplified into (integer -17 17).

Note: it is relatively easy to corrupt the heap when weak type checks are used if the program contains type-errors.

Used when (and (< safety 2) (< safety speed))

No Type Checks

All declarations are believed without assertions. Also disables argument count and array bounds checking.

Note: any type errors in code where type checks are not performed are liable to corrupt the heap.

Used when (= safety 0).


I'm not familiar with gradual typing, but, SBCL with any safety level above 0 does both of those things. This isn't specified by the standard, of course.




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

Search: