CL has static typing and such in at least three important senses that aren't usually called out explicitly in these discussions. First, you can annotate types and some compilers (notably the popular SBCL) can warn you, at compile time, about issues around using the wrong types, undefined vars, unused vars, wrong arguments passed to function, etc. I've read somewhere that's all based on Kaplan-Ullman type inference developed in the '80s, along with an example implementation for CL: http://home.pipeline.com/~hbaker1/TInference.html This is the sense of using types to help you write more correct software. It's obviously not as rigorous as Java/Haskell/Shen and not everything can be done at compile time. On the other hand CL has very flexible type definitions, so you get possibilities like "integers 2,3,4,5" as a type rather than limited to "all integers" or custom types like "is keyword :a or :b or :c".

Second, compilers can use type information (or inlining hints, etc.) to compile efficient machine code, which you can inspect with the built-in function 'DISASSEMBLE.

Third, types are used in the CLOS system to support efficient multiple dispatch for multimethods, and the rest of the CLOS and MOP machinery that makes it a very "non-traditional" (despite CLOS being first to ANSI standardize) OOP system with a lot more power than other fashionable languages provide. I'm basically in agreement with the title of http://www.smashcompany.com/technology/object-oriented-progr... with the caveats that Lisp is different and an exception (even if not perfect, there's an unfortunate mismatch in methods not allowing any type for dispatching on, though you can work around it in a similar fashion to Clojure's multimethods of dispatching on a runtime value) and that carefully designed Java can make the forced OOP tolerable.

CL is also super dynamic and lets you redefine basically everything so none of this is truly "static", and that's why compilers will warn rather than error, and runtimes while developing will preserve your state and drop you in a debugger instead of destroying state, printing a stacktrace, and giving up, because you can fix it and recompile that little bit or rerun after defining a missing variable. CL's conditions and restarts system has yet to be convincingly cloned by other languages.

Contracts, DSLs, immutable data structures, simple primitives, and other things (some not present in any other languages) are available in CL... My own reading has found that a lot of them have been there or in the predecessors to the CL standardization or in things built on top since for a long time (some well before I was born) and explored by big production business applications, not just academic exercises... Some of course are more modern transplants as they haven't gotten popular until recently. But for the things that were there already, in a sense the discussions have already been done and may help explain the lack of driving force for them now. In other languages I see them driving themselves close to where CL already is more often than driving to a completely new place (but then CL provides and lets you go there too, or at least somewhere close). You're free to use these things in CL, or not; you're right that it's not an opinionated language and I'd argue never was. Fortunately there's enough capability for modularization that we can have different opinions (e.g. the meaning of syntax like [Click me] in a UI component) and still trivially share code. It's a shame that Clojure code and CL code can't be trivially shared.