Hacker News new | ask | show | jobs
by vaylian 78 days ago
Clojure is the language that made me "understand Lisp", as originally stated by Eric Raymond and citet by Paul Graham: https://paulgraham.com/avg.html

It seems like a small thing, but Clojure's choice to open up for other types of parentheses made seeing the structure of lisp programs much easier. This helped me understand how code is data and how macros are functions that can transform both code and data.

An important design philosophy (which is also hinted at in the trailer) is "simplicity". Clojure is designed to give you the tools to build simple solutions to the problems that you want to solve. It approaches mutability, which is one of the key sources of complexity in programming, with immutable data structures. It's a really clever way to do functional programming where your data is copied a lot but the copies are lightweight.

I don't write Clojure any more these days. I'm mostly doing Rust. But it is true what Eric Raymond said: Lisp has made me a better programmer.

Also: XKCD 224 and 297

1 comments

Lisp philosophy is all about inventing languages (libraries), creating abstractions for each problem. Clojure is all about using primitive data types and maps everywhere explicitly.
virtually all abstractions are built on top of primitive data types and mappings
> virtually all abstractions are built on top of primitive data types

Obviously. The point being made is that the Clojure style discourages building DSLs and the like and prefers to remain close to Clojure types and constructs. It departs in various ways from traditionally Lisps.

> Clojure style discourages building DSLs

does it really? https://github.com/simongray/clojure-dsl-resources

DSLs typically involves constructing macros that are domain specific (to cobble together a domain specific programming language on top of the host). Most of the linked examples are not macro based and are the exact opposite. They specifying domain specific data layouts built directly using the Clojure-native immutable datatypes. They don't create Domain specific datatypes or function-generating wrappers. It's just rarely necessary

A good example is making GUIs in Clojure. At first there was a cool macro based system called `fn-fx` that maked a JavaFX GUI. Then vlaaad wrote `cljfx` which just used plain Clojure maps and removed the macros entirely. This increased the boilerplate a tiny amount but made the system much more flexible and extensible

> DSLs typically involves constructing macros that are domain specific

a DSL is a constrained language for expressing domain concepts.

in traditional Lisps they are often syntax-oriented, because code is lists and macros are a natural tool.

in Clojure, pervasive use of keywords, vectors and maps allows you to shift DSL design towards data interpretation rather than syntax transformation.

so in Clojure doesn't discourage DSLs - clojure practicioners simply prefer data-oriented DSLs to macro-oriented ones, mostly because they are easier to reason about and process with existing tools, while macros are used more selectively.

I think you're talking past each other.

"DSLs" can both mean "Using the language's variant of 'arrays' to build a DSL via specific shapes" like hiccup in Clojure does, and also "A mini-language inside of a program for a specific use case" like Cucumber is its own language for acceptance testing, but it's "built in in Ruby" in reality.

Clojure favors the "DSLs made out of shapes" rather than "DSLs that don't look/work like lisp inside of our programs".

no, not really. when people talk about DSLs in context of lisps, they usually still mean staying in the domain of s-expressions.