(defclass foo (superfoo1 superfoo2)
((some-slot :type bar)))
(defmethod baz ((some-foo foo) (some-bar bar))
...)
(defmethod foobar ((some-foo foo))
(baz foo (make-bar)))
What would you need to do refactoring operations on such code?
Given that there are classes, arguments are specialized over classes, slots have types, ...Some tool that can point where in a 1M lines of code project those classes are being used, and if they would need to change.
That's a good thing. But then comes the git merge (or any other automatic code altering tool). How do you know something hasn't been messed up in the process ? (unless you wrote unit test for every argument of every function)
Lisp has compilers.
Some do also some type checking, here SBCL 1.5.2:
(declaim (ftype (function (fixnum) fixnum) foo))
(defun foo (a)
(+ a 1))
(declaim (ftype (function (fixnum) string) bar))
(defun bar (a)
(if (zerop a)
"zero"
"not-zero"))
(defun baz (a)
(foo (bar a)))
Then: * (compile-file "/tmp/test.lisp")
; in: DEFUN BAZ
; (FOO (BAR A))
;
; note: deleting unreachable code
;
; caught WARNING:
; Derived type of (BAR A) is
; (VALUES STRING &REST T),
; conflicting with its asserted type
; FIXNUM.I had convinced myself I was reading Clisp, instead of CLOS.
Common Lisp has an object system with classes since the early 90s. In fact it was the first standardized object-oriented language.
Common Lisp also has optional type declarations. Not very sophisticated, but they are there.
Check out the SBCL implementation, which has a compiler which does some static type checking/inferencing.
But one usually can use types/classes at runtime, too.
But that’s another topic.