People admire Lisp's "elegance" in that it only ha...
# thinking-together
c
People admire Lisp's "elegance" in that it only has a single built-in datastructure - lists
(a b c)
. Clojure, on the other hand is generally admired for being more "practical". One of the main things Clojure introduced is vectors
[a b c]
, and maps
{:a b, :c d}
as first class syntax. I was reading some Lisp this week and my brain kept grating/complaining because I was seeing what are conceptually hashmaps written as what I was interpreting as a lists of pairs, something which I "know" to be different. Conversely, I have always thought it was annoying that C++ has three different operators (
::
,
.
,
->
) that all essentially mean "member of". Would C# be better if you had to say
System::Console.Print()
instead of
System.Console.Print()
? No, I think most people would rarely feel the need to conceptually distinguish between these things, the C++ syntax is just annoying noise to me. What is it that distinguishes Clojure's brilliant decision to expand the syntax, from C# brilliant decision to compress the syntax? It implies to me that if there is a scale of simplicity-to-expressiveness, then humans just happen to sit at particular point on it. There's no particular "reason" for why these changes were right other than "they'd gone too far that way, go back this way". There's a local maximum somewhere in the middle. I have been thinking about this simplicity-to-expressiveness scale recently as it irrationally annoys me that on WikiData, "instance of" is "just another relationship" (it's P31 - "citizen of" is P27!). I think that RDF is far too far towards the "elegance" end of the spectrum and would greatly benefit from a Clojure-style acknowledgement that some things are more different, and should be more differentiated. Yeah, it's mildly interesting that Node-Rel-Node triples is all you need to describe an ontology, but that's not actually how people think about the world...
👆 1
🤔 1
🎆 1
i
In the C++ case it's a distinction without a difference. In the lisp case it's a difference without a distinction.
☝️ 2
💯 5
Differences and distinctions should match 1:1
👍 1
Daniel Jackson's concept modeling work does a good job of giving a framework for why
💡 2
👍 1
j
Tools, tasks, and people are a triple. If you keep two the same you can find a local maximum for the third. But what you learn doing that isn't transferrable to different tasks, tools, and people. And maximizing only one would have to be justified by expecting the other two never to change. It's never just one spectrum, like "elegance". With Clojure and C#, it might be that they were opposite sides of the same local maximum, because the task and people are similar. Maybe not. RDF has a completely different triple, so the lessons aren't transferable, I would expect. I would also say that if a tool doesn't reflect how people think about the world that doesn't necessarily mean there is anything wrong with the tool. It might suggest the utility of another, different tool, aimed at different (or just more) people.
👍 1
g
IMO... The beauty of assembler, lisp, lambda calculus, triples, etc. is that they have “no syntax” and don’t restrict what you can do. The beauty of C++, Smalltalk, Clojure, etc. is that they “have syntax” and restrict what you can do. “Local maximum” is just that - local. There are many local maxima. Schmooing all possible notations into “one language to rule them all” results in complexity, poor UX, epicycles, watered-down unions of features, etc., etc. Disclaimer: I am a Lisper and a PEGer (Ohm-JS). Syntax is cheap. Deprecate programming languages.
a
Expanding on @ibdknox's point a bit, C++'s various member/scope operators all have basically the same signature of
(group, selector) -> thing
. So it doesn't hide or obscure any semantics to use the same syntax. Lists and hash maps do not have the same signature; a list is flat, but there are internal relationships in the arguments to a hashmap. So it helps to have different syntax to remind you of that.
j
@ibdknox’s take, absolutely. C++ adds complexity that doesn't provide any (useful) expressiveness. So it isn't even on the Pareto frontier of the simplicity/expressiveness tradeoff space. I personally take Lisp vs Clojure as a better example of a legitimate tradeoff close to the frontier. I also think it's bonkers that the smallest Wikidata property, P6, is "head of government". Shows you what Wikidata thinks is most important. 😛
r
Adding maps to Lisp syntax, which Clojure does but doesn't fully embrace, makes the homoiconic data structure more like JSON. The CONS cell is dead anyways - I don't really like Clojure's distinction between
(lists)
and
[vecs]
as they aren't really orthogonal, and the maps are just lists of pairs, so malformed ones will be ambiguous as to whether they're missing a key or value, like
{ :a :c 2 }
, as opposed to Javascript's
{ a: , c: 2 }
.