3 ms·
Common Lisp both has strong dynamic type checking as well as optional static type checking. For example, you can declare the static types of function parameters
by _ph_ 10y ago
Common Lisp both has strong dynamic type checking as well as optional static type checking. For example, you can declare the static types of function parameters and the return results. For a good compiler using static type declarations, look at SBCL, which makes excellent use of type information to get up to C like performance of the compiled code. It also is very good about type inferencing. So if it knows the input types for a function call, it usually can infer the function result type and use that for further type reasoning.
Common Lisp of course has defined name spaces. They are called packages.
Yes it has eval, but I have not seen a Lisp program in years which used it. And it would be easy to lint programs so it is not used, if you had a reason to be afraid of it.
- muflax 10y agoHow does static type checking work in CL? One of the most important use cases for static typing is safe modification of existing code, like during refactoring. So a typical example: I have some struct with a field of one type, say a string. I use it in a few functions, reading and writing it. Now I change the field to a different type, say an array of strings instead. I want the compiler to tell me about all the code that's now invalid. How do I do that? I quickly wrote up a simple example of the (statically) untyped code I mentioned: http://pastebin.com/f7KWETvT http://pastebin.com/f7KWETvT (I can also write a matching example in some common static language (like C or ML), but I think it's clear what I mean.) What type annotations do I add to make that basic use case work? So what do I add such that it first type-checks when name is just a string, then change the annotation to make name an array of strings, and get two compile-time errors because the functions are now wrong. (Unfortunately, I only know a little bit of CL (and even then mostly due to familiarity with Emacs Lisp), so my example might be a bit un-idiomatic. Feel free to turn it into idiomatic CL if something is too weird!)
- _ph_ 10y agoIf you wanted to define a type-safe person struct, you could do it with: (defstruct person (age 0 :type fixnum) (name "" :type string)) Now every access to that person structure should be checked by the compiler. You can create a person like: (setf p (make-person :age 7 :name "fred")) => #S(PERSON :AGE 7 :NAME "fred") But not with: (setf p (make-person :age 7 :name 8)) which causes SBCL to error with: The value 8 is not of type STRING. [Condition of type TYPE-ERROR] Equally, if you tried wrongly to define (defun print-hello (person) (let ((name (string-upcase (person-age person)))) (format t "Hallo ~a!~%" name))) You get at least a warning you should heed: ; caught WARNING: ; Asserted type (OR (VECTOR CHARACTER) (VECTOR NIL) BASE-STRING SYMBOL CHARACTER) ; conflicts with derived type (VALUES FIXNUM &OPTIONAL). So, for refactoring, you would change the type signatures of your struct and then recompile all code to see whether the compiler generates errors/warnings.
- muflax 10y agoThanks! I vaguely remembered there being some problems with that, but playing around with it, it works fine and as I'd expect. Sweet! Gotta revisit CL soon then.