4 ms·
(defun foo (x) (declare (type list x)) (car x))
by jgrant27 17y ago
(defun foo (x)
(declare (type list x))
(car x))
- gwern 17y agoSorry, still just a warning: $ sbcl This is SBCL 1.0.18.debian, an implementation of ANSI Common Lisp. More information about SBCL is available at <http://www.sbcl.org/> http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. * (defun foo (x) (declare (type array x)) (car x)) ; in: LAMBDA NIL ; (CAR X) ; ; note: deleting unreachable code ; ; caught WARNING: ; Asserted type LIST conflicts with derived type (VALUES ARRAY &OPTIONAL). ; See also: ; The SBCL Manual, Node "Handling of Types" ; ; compilation unit finished ; caught 1 WARNING condition ; printed 1 note FOO
- jgrant27 17y agoFirst of all, you have modified the function that I posted (you changed the type declaration from a list to an array). Second, you do not read your compiler warning messages. SBCL is trying to tell you that you shouldn't type something as an array when you are clearly attempting to use it as a list e.g. calling the CAR function on an array makes no sense. A list and an array in Lisp are not the same. The CAR function in Lisp only works on lists. * (defun foo (x) (declare (type array x)) (car x)) ; in: LAMBDA NIL ; (CAR X) ; ; caught WARNING: ; Asserted type LIST conflicts with derived type (VALUES ARRAY &OPTIONAL). ; See also: ; The SBCL Manual, Node "Handling of Types" It's correctly warning you before you even try and call the foo function, because it will fail no matter what you pass to it !
- gwern 17y ago> First of all, you have modified the function that I posted (you changed the type declaration from a list to an array). How would I demonstrate SBCL's ability to detect type errors except by making a type error? Your example showed nothing; 'type' could be a null-op for all it does. And checks about primitive types are all well and good, but how far does it go? Not being much of a lisper, it's hard for me to give whole classes of example where SBCL's warnings are non-existent, incorrect, or buried under a flurry of others. If I declare a custom CLOS object with multiple fields/methods/whatever and call a field/method which doesn't exist, is SBCL still smart enough to warn me? I dunno.
- jgrant27 17y agoThere is no concept of a 'primitive' type in Common Lisp. It handles type-checking for built-in types or for your own custom declared types. CL's type system is very powerful. Here's a type-checking example related to CLOS : ;; High safety settings are required by SBCL for type checking of slots ;; See --> http://www.apl.jhu.edu/~hall/Lisp-Notes/Defclass.html (declaim (optimize (speed 0) (compilation-speed 0) (safety 3) (debug 3))) (defclass circle() ((center :type cons :accessor circle-center :initarg :center) (radius :type fixnum :accessor circle-radius :initarg :radius))) (defmethod circle-area ((x circle)) (* pi (expt (circle-radius x) 2))) (let ((c (make-instance 'circle :center '(0 0) :radius 4))) (format t "~A~%" (circle-area c)) (setf (circle-center c) '(2 3)) (setf (circle-radius c) 7) ;; this will fail at compile with a TYPE-ERROR ;(setf (circle-radius c) "B") ;; this will fail at compile with a UNDEFINED-FUNCTION ;; because the method does not exist ;(location c) )
- gwern 17y ago> (let ((c (make-instance 'circle :center '(0 0) :radius 4))) ... Erm, what? This is supposed to show smart compile-time checking about runtime behavior?? This no more demonstrates what you apparently think it demonstrates than I could demonstrate Haskell's type-soundness by taking some Template Haskell, inserting 'head []', and saying 'it crashes during compilation, eureka!' What would be fairer would be wrapping all that in a '(defun foo () )', in which case one doesn't get any warning relating to the 'location c' or "B": * (load "foo.cl") STYLE-WARNING: Implicitly creating new generic function CIRCLE-AREA. ; in: LAMBDA NIL ; ((LET ((C (MAKE-INSTANCE 'CIRCLE :CENTER '# :RADIUS 4))) ; (FORMAT T "~A~%" (CIRCLE-AREA C)) ; (SETF (CIRCLE-CENTER C) '(2 3)) ; (SETF (CIRCLE-RADIUS C) 7) ; (SETF (CIRCLE-RADIUS C) "B") ; (LOCATION C))) ; ; caught ERROR: ; illegal function call ; ; compilation unit finished ; caught 1 ERROR condition T
- Hexstream 17y agoActually, if I understood the HyperSpec correctly, in theory a conformant Common Lisp implementation would be allowed to just crash if you declared that x is a list and then you call it with something else. By declaring the type like this, you're telling the compiler: "I assure you that x will definitely be a list". Of course, in practice implementations like to check everything by default.
- jgrant27 17y agoThe compilation parameters speed and safety will determine what happens when something goes wrong. For example, the following global settings would be considered fast but dangerous : (declaim (optimize (speed 3) (compilation-speed 0) (safety 0) (debug 0))) These would be safe but slower : (declaim (optimize (speed 0) (compilation-speed 0) (safety 3) (debug 3)))