Unfortunately, powerful tools also means custom solutions which doesn't work that well in large teams.
Other language limit what you can do with abstraction. You get libraries with less nice api's but you have less digging to do to understand a piece of code that make use of them.
Racket has typed racket, but then you are getting into pretty obscure territory. You might be able to have strict standards for your own code, but you'll still be plugging in to a dynamically typed ecosystem.
Statically typed/compiled languages (IMO) take more upfront thinking and usually support top down development.
Lisp & Co on the other hand are excellent for exploratory , repl based, bottom-up development.
No need to exclude one in favour of other. Both can be used depending on the requirements.
A good litmus test for complexity is the following: as a developer analysing software in order to understand & modify it, how many lines of code do I have to read in order to grasp what is going on and what can I do to solve my problem?
In my opinion this is the main goal of a good software architecture. The advantage of lisp is that I can create a DSL like library that precisely describe my domain. The issue is that because macros can have dramatic effects on the final program, I have to check carefully all of them in order to understand a piece of code. This and the inability to look up quickly what fields are inside an object or the exact api of a function.
A common base language and static types are the best tools I know to create useful boundaries. Another way is to split the software but this comes with other issues.
The use of the term "powerful" might be a bit misleading. Powerful is good. Here powerful refers to "easy metaprogramming". Metaprogramming is something you need in an ecosystem, but you need to hide it a bit so that you only use it when you really need it. I find the lisp community a little bit too proud of their metaprogramming capabilities.
Do you have an example where you had to carefully check a macro when writing your Lisp code? I have never looked into macro code more closely than function code when writing Racket programs, and mostly I don't know or care if whatever I am calling is a macro or a function.
> This and the inability to look up quickly what fields are inside an object or the exact api of a function.
At least within Clojure and Racket, you have IDEs like Cursive and DrRacket that will show you function documentation and do code completion. Or are you saying that the presence of macros alters this somehow?
I'm not sure that lines of code alone are that useful here, or APL would be everyone's idea of a perfect language, since it can express so much in so few lines.
The Lisp community in particular seems to value verbosity over terseness, preferring long, descriptive function names and variable names, which make for more lines of code, but arguably greater readability.
I personally value clear code far higher than terse or clever code. I'd much rather read over a page of easily understandable code in 5 minutes than puzzle over a single line that does the same exact thing for an hour.
Lisp on the other side not only had less of that collective experience due to becoming less popular, but it was also famous as the language that gives super powers allowing programmers to do 10x more, so the experience was also biased for single dev performance. The Lisp Curse is a cultural problem, not a technological one, you don't need to reinvent stuff just because it is easy (and fun).
I'm optimistic though since the new generation of languages (closure, elixir, julia, nim, rust) is increasingly going against the rooted belief in OOP (stuff like inheritance) and incorporating more Lisp features like macros, code as data and everything as expression. This means more and more large dev groups will have access to the tools and reason to make it scalable in order to get a little of that super power under control.
If types are your thing, shen lisp is an interesting language. Lisp with sound types (to the point of literally embedding sequent calculus in the language) and others traditional functional features like pattern matching.
That doesn't mean what I imagine you're implying: that we can make writing the code harder without any cost.
I just think the choice of programming language (unless it's pathologically bad, e.g. writing device drivers in Python) is a minor factor in real world software engineering.
I don't know about that. A language is not merely a language. It comes with the entire eco-system, libraries, community etc. Not to mention your personal expertise and preference.
I am certain depending on your language selection, your development experience and the quality of output will vary dramatically.
For example Java, Javascript, php, Go, python, ruby are all valid choices for a web application. Depending on what you choose, your experience will be different no?