I guess your definition of practical differs from mine. For me practicality is tied directly to usability in solving a widely disparate set of problems. This means that flexibility is key. The language I use should not only be able to bend and adapt to the problem at hand but also _not constrain my thinking_. The latter is also known as 'metalinguistic abstraction' and is strongly expressed in SICP as the philosophy of Lisp. Clojure mostly bypasses that since it has a very opinionated but also very constrained view on the problem-solving design space.
As an example of metalinguistic abstraction, some of the tasks I've successfully deployed Common Lisp at include creating a high-performance network stack that runs on ARMv8 and is based on JIT compilation and an entire assortment of solutions that sit on opposite ends of the highlevel-lowlevel spectrum. Concepts such as tight control over memory, stack allocation and one-to-one mapping with generated instructions were critical. Common Lisp allowed me not only to successfully investigate the domain but also to use the resulting code in production. For these tasks, Clojure would have been a total miss both due to implementation decisions (JVM) and its constraining nature -- in this case, immutability, memory and compilation model -- not allowing me to come up with a 'language' that will let me think the right thoughts.
Comments
I guess your definition of practical differs from mine. For me practicality is tied directly to usability in solving a widely disparate set of problems. This means that flexibility is key. The language I use should not only be able to bend and adapt to the problem at hand but also _not constrain my thinking_. The latter is also known as 'metalinguistic abstraction' and is strongly expressed in SICP as the philosophy of Lisp. Clojure mostly bypasses that since it has a very opinionated but also very constrained view on the problem-solving design space.
As an example of metalinguistic abstraction, some of the tasks I've successfully deployed Common Lisp at include creating a high-performance network stack that runs on ARMv8 and is based on JIT compilation and an entire assortment of solutions that sit on opposite ends of the highlevel-lowlevel spectrum. Concepts such as tight control over memory, stack allocation and one-to-one mapping with generated instructions were critical. Common Lisp allowed me not only to successfully investigate the domain but also to use the resulting code in production. For these tasks, Clojure would have been a total miss both due to implementation decisions (JVM) and its constraining nature -- in this case, immutability, memory and compilation model -- not allowing me to come up with a 'language' that will let me think the right thoughts.