Their use of metaprogramming doesn't just allow you to extend the language, it really expects that of the programmer. Which means you have to assume the role of language designer to some extent. Learning how to do that definitely feels like a way to level up your skills. But it seems uncommon for people to want to do that.
It becomes more obvious once you start managing developers vs being a solo dev. everyone making their own designer means the language can morph into a completely insular creation with a learning curve that expands exponentially with every new hire. A little extra boilerplate is the cost of standardized idioms that work across both your codebase that your new hires are already familiar with from working in that language at other companies. its why go was created. personally I prefer rust and elixir as good middle grounds.
Lisp devs are managed in the same way as any other: You have style guidelines, design review, code review, etc. Sometimes a new macro is good and vastly simplifies code. It's accepted as a PR and documented like anything else. Sometimes a new macro is bad, and it's promptly rejected by the team. It's a persistent myth that Lisp programmers are just going to design their own little languages everywhere in a shared code base and it'll be impossible to understand.
(Case in point: Look at open source Lisp code. There isn't even management or code review there! Yet the vast majority of Lisp code is actually just functions and classes, with the occasional macro to reduce boilerplate. In some circumstances, you have a library offering a macro, and it's actually well documented and easy to understand. See Iterate, SERIES, etc. for actual examples.)
Rust or Elixir or Java or whatever aren't at all immune to monstrosities created by astronomically complex or baroque abstractions, FactoryFactoryFactories, and so on. How do teams avoid those? Style guidelines, design review, code review, etc.
Programs are rarely linear; why do you expect code to be?
But beyond that the thing I don't understand about the modern hate towards macros is that they are simply very fun.
If you can write a meta program for it, you can execute that in CI and spit out generated code and be done with it. This is a viable approach in any programming language that can print strings to files.
It’s not frustrating, but maybe it feels tacky. But then you shrug and move on to the real task at hand.
One such example is the let-alist macro in elisp
https://www.gnu.org/software/emacs/manual/html_node/elisp/As...
Dealing with nested association lists is a pain. this let you write your code with a dot notation like jq.
Macros are not only for solving a particular task (serialization, dependency injection, snippets,…) they let you write things the way it makes sense. Like having html-flavored lisps for template, sql-flavored lisp for query,… Lisp code is a tree, and most languages are trees, so you can bring easily their semantic in lisp.
Meta-heavy code usually offers a nice DSL, but is proportionally harder to drill down through.
(prog ((a 0)
(b 1)
(c 0))
(declare (type Fixnum a b c))
:fb-start
(print a)
(incf b a)
(setf a
(- b a))
(incf c)
(when (< c 100)
(go :fb-start))) let a, b, c = 0, 1, 0
fb_start:
writen(a)
b +:= 1
a := b - a
if c < 100 do goto fb-start- Every day that passes, the gulf between Lisp's tooling and what a typical user expects grows wider. It needs to escape Emacs and SLIME to something that feels complete and polished.
- There needs to be a little bit of a culture shift around Lisp to actually write programs that do things. How many programs can you download via apt or brew that are written in Lisp? They're executables at the end of the day so nothing in principle stops this from happening, but there's just a thread of modern Lisp culture where it's more fun to play around in the REPL and write creative libraries than to ship. (There are notable exceptions of course.)
- I personally like the quirkiness of Common Lisp, but there are so many ways to write it (imperative, functional, etc.), so many ways to structure your programs (one package, package per file, package inferred system, etc.), and so many ways to offer APIs (plain old data and functions, generic function protocols, etc.) that it makes it a combination of confusing and intimidating. I think shifting toward something a little more structured and disciplined like Coalton, while still giving the escape hatches to all of Common Lisp, would help a lot of people "join in" on building new code or building upon existing code.
- ICL https://github.com/atgreen/icl/ a full featured REPL in the terminal and the browser.
- JSCL's playground 100% in the browser https://wiki3-ai.github.io/jscl-kernel/ (very new)
- constantly new editor plugins. A new one: Zed https://github.com/etyurkin/zed-cl (all editors, for readers, including VSCode, Pulsar etc: https://lispcookbook.github.io/cl-cookbook/editor-support.ht... Those editors appeared in recent years. So, I see a good trend in the ecosystem).
Can you give specific examples of "what a typical user expects" that are missing from Emacs-based programming environments (SLIME, and/or others)? I'm not suggesting there aren't any, I'd just like to know your list.
Lisp is also a symbolic language. Meaning the code work on symbols, not data, only at evaluation the value of the symbol is known. There’s a lot of symbols manipulation routines like macros, intern, package loading,… that prevent to statically know the code.
It’s why people use the REPL flow.
- There is Calva for VS Code but the community default is emacs and cider
- How many programs in apt or brew are written in clojure? I'd concede that the community is great and focused on productivity, but it's so niche that you don't see much work out there made in clojure, and there is also a vestigial lisp sentiment to prefer building your own library from scratch instead of contributing to a standard library, which spreads the efforts of a small community too much
- Third one you need to mutate it a little bit: clojure is opinionated instead of having "so many ways", but its opinions, while great, are foreign to most programmersEmacs isn’t required. You can always create a REPL plugin. Emacs just does a lot of heavy lifting for you due to comint, sexp navigation, and process management being included.
> building your own library from scratch instead of contributing to a standard library
Simple data structures lead to very generic function. You don’t have to write tower or massive spread of abstractions like in Java or TypeScript. A struct is nothing than a hashmap that can help a typechecker. Most lisp programs prefer primitives or functions instead of manipulating complex objects -never ‘buffer.name’ but ‘(get-buffer-name buffer)’-.
From a module, what you need are functions and an opaque state holder.
With such philosophy, you don’t need a lot of libraries, which are often designed to be complex, when you need a simple model.
> Third one you need to mutate it a little bit
You don’t. Clojure already does the optimization for you for the standard data structures, and they are the only things you need in most cases.
i wrote a tiny scheme evaluator as a learning exercise and it was probably the best investment of a few weekends i've ever made as a programmer.