3 ms·
Fine, but there is surprisingly no mention of Lisp in the related work, which defines a COMPILE function in its specification. In a language where the compiler
by junke 11y ago
Fine, but there is surprisingly no mention of Lisp in the related work, which defines a COMPILE function in its specification.
In a language where the compiler is part in your runtime, type checking is equally available at different execution times.
I mean, when I connect to a running instance of SBCL (Common Lisp) to compile my programs, that's exactly what happens: static-type analysis at runtime.
Let's say I define a function which builds a function and compiles it:
CL-USER> (defun foo (x) (compile () `(lambda (u) (aref ,x u))))
FOO
Call it with an array:
CL-USER> (foo #(2 3 2))
#<FUNCTION (LAMBDA (U)) {100B3C610B}>
NIL
NIL
The resulting closure allows to access elements of that array:
CL-USER> (funcall * 0)
2
Call FOO again, with a bad input:
CL-USER> (foo 332)
; in: LAMBDA (U)
; (AREF 332 U)
;
; note: deleting unreachable code
;
; caught WARNING:
; Constant 332 conflicts with its asserted type ARRAY.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
; printed 1 note
#<FUNCTION (LAMBDA (U)) {100B41E16B}>
T
T
COMPILE reports a type error (an exception that I could handle if needed).
- scott_s 11y agoIs it catching the type error before executing the code with the type error? The technique presented by the authors does not wait until there's a type mismatch in an individual expression inside of a function. It catches the type mismatch before executing the function. That's what they mean by "just-in-time static". It happens "just-in-time" because it's during program execution, but it's "static" because it happens before executing the function itself.
- junke 11y agoYes, during compilation. (defun foo (x) (compile () `(lambda (u) (print "Executed") (aref ,x u)))) (foo 0) ... reports a compilation error and of course does not print anything. If however I directly type the offending form (aref 0 0) a runtime type error is signaled.
- scott_s 11y agoI believe that is still quite different from the technique presented by the authors. Their technique applies at program execution, but prior to the execution of the individual functions. What you're showing is all prior to program execution.
- TeMPOraL 11y agoNo, this is during program execution. Lisps blend compile time and run time together. You always have a compiler available, so you can compile new stuff (and recompile existing stuff) in the middle of your program's execution. And compile-time typechecking occurs whenever you compile.
- junke 11y agoThe type analysis happens only after I enter "(foo 0)" in the REPL, which is execution time.
- ufo 11y agoCommon LISP is a bit weird because its type system was originally designed primarily as a way to speed up the executables (by letting the compiler aggressively optimize memory representation and remove runtime checks). Nowadays that kind of efficiency isn't as big of a deal as it used to be and people tend to go more towards the angle of using the type system for error detection but I still can't shake that feeling that CL's type system feels a bit off when you compare it to other modern type systems. (this is no excuse to not at least cite Common LISP though)
- rurban 11y agoNo it's not. That's exactly the same use-case those slow dynamic languages have now. This kind of efficiency is a big deal, in languages designed by people with the same mindset. Getting errors is the same if at compile-time or in the test-suite or at the customer, though having them at compile-time is of course preferred. In LISP you have all 3 cases. In static languages only the first. These guys here solve their type-checking performance problem by deferring the check to dynamic code. Checks are expensive if your type checking code is slow, or the source code is a dynamic mess. We are talking about ruby on rails here, which is the biggest dynamic mess one can think of. It's the similar problem the JIT guys have, deferring compilation to only actually invoked code and skipping dead branches.
- lispm 11y agoA compiler with some compile time type checking has been implemented starting around 1985. That's the public domain CMUCL compiler (named Python) by Robert MacLachlan. See 'Types in Python' from the manual: https://common-lisp.net/project/cmucl/doc/cmu-user/compiler.html#toc127 https://common-lisp.net/project/cmucl/doc/cmu-user/compiler.... A variant of that compiler is used in the now popular SBCL implementation: http://www.sbcl.org/manual/index.html#Handling-of-Types http://www.sbcl.org/manual/index.html#Handling-of-Types