Learning Lisp has a tricky part, and one of my classmates in undergrad despaired of ever learning it, but surely Rust is harder to learn than Lisp, which makes me wonder what you mean by "Lisp has a higher barrier to entry".
You have to first install a Lisp compiler whose REPL is so spartan than even using arrow keys causes errors in your terminal. You have to learn Emacs. Figure out wtf SLIME and Paredit are from docs written in piecemeal plaintext READMEs. Then learn from a book that's older than you that makes no reference to any of the tools you just labored over installing. Then get a bunch of conflicting information about proper Lisp style from random patches of internet.
Who has time for that these days, except for the very determined and dedicated?
I think Lisp is a superlative language with excellent tools—once learned. But it hasn't had its UI revolution from anybody who cares enough to do the work.
Style is not essential to getting things done, but it's essential to building a community and having labor be multiplicative in its impact. Lisp is a language ripe for expressing a personal style, and that's antithetical to collaboration in a variety of ways. It can be managed, if the community can rally around a common set of principles.
I likewise have written Common Lisp for decades. But I also get paid to do it, manage a team that does it, and see immense value in doing these extra things that hackers don't much care for, such as:
- making Lisp compatible with other languages through ABIs
- developing stylistic guidelines
- developing systems for static typing in Lisp to assist long-term development and maintenance of Lisp code
- etc.
So does style or the lack of any of the aforementioned bullets "block" the ability to "get things done"? Strictly speaking, no, but it inhibits outside interest in your project.
None of the assignments my classmate struggled with required him write code that processes code, so I don't think that was the source of his confusion.
My guess is that it has more to do with the fact that CONS takes a whole list as an argument, then returns a different whole list, which superficially seems too computationally expensive to do in a loop.
-> A symbol can be an identifier and just a piece of data.
Above, the first DEFUN is a standard identifier of the programming language Common Lisp. The second DEFUN is just a symbol.
The first DEFUN form is a program. The second DEFUN expression is just data. Thus it makes no sense to indent the second DEFUN expression like a program. We don't know if it is a program, it could be just anything.
-> A list can be data and a program.
This specific double nature of built-in data structures, here symbols and lists, is already a hurdle to get over.
The developer has to know which lists are data lists, which are forms and which are expressions in inside a form.
(cond ((quote (a))))
->
(cond ((quote (a)))) is a form, which is meant to be evaluated
(a) is data
((quote (a))) is a clause of COND, which is neither data, nor a form to be evaluated
Thus the user has to understand that in Lisp these lists serve different purposes. Which is which depends on the context and the Lisp syntax & evaluation rules.
This then even may make functions possible which contain their own definition as data: