I'm amused by the fact that when you criticize LISP's syntax, defenders always say the syntax doesn't matter and real Lisp programmers don't even see the parenthesis. But then you look at these implementations of Lisp-like variants of existing programming languages and the thing the developers are most enamored with is the repetitive, parenthesis-laden syntax of Lisp, while keeping the majority of the non-Lisp semantics in tact (adding just a few functional conveniences like first class functions).
I'm not even criticizing, most of these are hobby projects and you can code how you like. I just think it's funny how hard Lisp clings onto the parenthesis thing while claiming the parenthesis thing doesn't matter.
The thing that matters is that code is written as s-expressions, which has a simple textual serialization format with lists, symbols, numbers, strings, vectors and a bunch of other data types. Thus any Lisp form is automatically data: not simple strings or complex syntax trees.
This enables a bunch of stuff: code can be relatively easily treated as data. It allows easy code generation, transformations (-> macros), traversal (-> interpreters/compilers) or editing.
The parentheses are just a part of the s-expression textual syntax. The s-expressions then are used by basic operations like READ, MACROEXPAND, PRINT and EVAL. Additionally many of the primitive data functions can be used to manipulate code: first/rest, list, append, reverse, map, ...
Yes exactly you have to separate the abstract idea of s-expressions in memory from their textual syntax (parentheses).
S-expressions in memory are a really really good idea and chronically underused in modern programming languages.
The parentheses are irrelevant to the core ideas of lisp. You can make a lisp using C-like braces and infix notation - what makes a lisp is the representation of the program in memory as a tree and the operations you can perform on that representation.
All the interesting macro expansion in lisp is performed after parsing, unlike in the C preprocessor, so you can write your programs using Egyptian hieroglyphics for all lisp cares.
> Yes exactly you have to separate the abstract idea
That was thought around 1960. Lisp had m-expressions in books. The actual Lisp system used s-expressions. The next few decades were often spend trying to get rid of s-expressions on the surface. Most of these attempts failed. If they succeeded they were something different. Like ML. One can think of the early ML as a kind of typed Lisp with a different syntax.
What Lisp made attractive was the similarity between internal and external representation. The Lisp system was internally manipulating programs as s-expressions - that was easier to understand when the external representation is similar.
> The parentheses are irrelevant to the core ideas of lisp.
S-expressions are an actual core idea of Lisp, while you focus on a minor aspect of s-expressions-> that s-expressions use parentheses to denote cons cells and lists.
Since the Lisp uses a certain data representation internally, it is much easier to use a simple textual format for that data externally too - one which makes the mental transformation easy. Using a complex and unrelated syntax does not make that easier, it makes it actually harder.
> All the interesting macro expansion in lisp is performed after parsing, unlike in the C preprocessor, so you can write your programs using Egyptian hieroglyphics for all lisp cares.
Actually that's not true: that's one of the ideas of Lisp and large programming system have been built around this. A Lisp system will expose its inner working to the programmer. Live and interactive systems are not an exception, they are the default.
But lispers are only a small % of programmers. So parentheses have been a success in the sense that lispers really like them, but have been a failure in the sense that they have prevented lisp's cool semantics from reaching a broader audience.
If you are a JS programmer or God-forbid a C++ programmer, you are already living in a world where the transformation from lexical syntax to AST is dozens or hundreds of pages with weird edge cases (e.g. JS semicolon insertion or C++ most vexing parse). If that can be reduced to 1 or 2 pages it's still a massive improvement from their perspective even if it looks like a downgrade to a hardcore lisper who eats parentheses for breakfast, lunch and dinner.
Lisp programmers's don't 'like parentheses' - parentheses is not what makes Lisp.
Lisp was designed to do programming with s-expressions (aka nested lists). That's its core original purpose. Lisp even means 'List Processor'. It was then early detected that this can be applied to Lisp itself, for example by interpreting s-expressions as Lisp programs.
'Parentheses' are just a part of the notation. If you take away the feature of s-expressions on the surface and thus also the notation, you are no longer programming on the surface in classic Lisp. You can always use alternative notations, but that will take away the seamless symbolic programming.
> failure in the sense that they have prevented lisp's cool semantics from reaching a broader audience
'parentheses' did not prevent that.
Over decades lots of original Lisp stuff was moved to other languages (garbage collection, image-based programming, functional programming, macros, etc.).
There are lots of languages which are somewhat re-invented or re-designed Lisps: Logo, Dylan, Julia, Ruby, ... One can already use those.
Lisp should drop s-expression-based syntax, so that C++ or JavaScript become different internally? This makes no sense.
> If you are a JS programmer or God-forbid a C++ programmer, you are already living in a world where the transformation from lexical syntax to AST is dozens or hundreds of pages with weird edge cases (e.g. JS semicolon insertion or C++ most vexing parse). If that can be reduced to 1 or 2 pages it's still a massive improvement from their perspective even if it looks like a downgrade to a hardcore lisper who eats parentheses for breakfast, lunch and dinner.
The issue is that code is read more often than it is interpreted, written, or compiled.
All the beautiful aspects of lisp make it decidedly unwieldy in production software. There’s a tendency of projects written in lisps to be unwritten in lisps as they mature.
> The issue is that code is read more often than it is interpreted, written, or compiled.
In a Lisp system, the code is always there and not just in textual forms.
> All the beautiful aspects of lisp make it decidedly unwieldy in production software. There’s a tendency of projects written in lisps to be unwritten in lisps as they mature.
There are two main factors which lead to Lisp software being rewritten:
1) deployment. In the early days it was the lack of resources (memory, speed, ...), but there are other factors like having a robust runtime or the ability to integrate in larger software around it.
2) familiarity. There are not many people available to maintain Lisp software. Not because the syntax is strange, but because the whole language is strange. There are no major other programming languages which work like Lisp, so few people can productively program in it. There are exceptions to it, like the simple Lisp used in AutoCAD and related software. These have millions of installations and the complexity on the Lisp side is not that huge - there it's mostly used as a simple interactive programming language.
What makes Lisp actually difficult for programmers is not the syntax, but the pervasive use of code as data, code transformations, various ways of meta-programming, etc. It's the features it was developed for: computing with symbolic expressions - here even applied to itself.
The language Lisp was built to compute with symbolic expressions, then the idea that a Lisp program is itself a symbolic expression is tempting... this then leads to center programming activities around this idea.
Frequently-used interpreted code is probably interpreted more than it is read. Most of the code in a large codebase is likely compiled more than it is read. One-off code is often written, compiled, and executed once, and read never.
If a piece of code is read more often than it's interpreted, written, and compiled, it's probably example code.
The rewrites tend to involve managerial decisions and not technical (arguably Reddit was one of the few cases where I can point to clear cut technical reasons, the reason being "we wanted to run FreeBSD and threads sucked there"). Sometimes it's internal politics (like JPL's C++ developers giving Lisp as reason for their code segfaulting...).
There's quite a lot of big systems written in Lisp. Unfortunately they rarely ever were opensourced, and we get to have blinders made out of our own limited experiences and common generational knowledge loss in IT.
You should look into Racket. Apart from getting some momentum due to the merger with Chez, it has a relatively big academic community backing it up.
And it's very different from other Lisps in the sense it's trying hard to be an ecosystem for language-oriented programming, which is probably taking the idea of macros to a new level.
I've used Common Lisp and Clojure for many years, but Racket looks more and more appealing to me.
> it has a relatively big academic community backing it up
this is actually a problem in my eyes and will prevent it from gaining industrial traction. for example, this keeps the main developers as a revolving door of graduate students writing code and the core maintainers as full professors who have priorities different from industrial users. secondly, the culture of racket is as a research language. they just replaced the runtime (loads of risks for industrial users), and now they are replacing the syntax. this does not create an environment enticing to industrial users. the racket team feels these changes will increase its user base, but i believe if that ever happens, these changes are deferring such an increase well into the future.
The parentheses give you Macros, a completely uniform calling convention, and the "everything's an expression" programming style. These are arguably the things you cannot get from a non-lisp language. Almost everything else varies between lisp implementations.
The lack of syntax matters in the sense that once you don't have any you realise that it just gets in the way. Having lots of parentheses is a small price to pay for powerful tools so that's why "it doesn't matter". Non-lispers generally don't understand how lisp is different from their language of choice and therefore don't understand why the lack of syntax is an advantage.
I know :) And that's cool, and that property is the base of my own programming language. I am also trying right now to find some explanation why it's cool based on some fundamental conclusions from theoretic computer science...
I just feel that when someone says that Lisp does not have syntax or that syntax is not important, it's plain wrong...
> I just feel that when someone says that Lisp does not have syntax or that syntax is not important, it's plain wrong...
I completely agree. I just feel that not every programming language needs to have the same approach to syntax. Lisp is different from most languages in its way to have a data syntax in which programs are written. Thus the data syntax is textual (s-expressions) and the program syntax is structural (based on data structures like lists, symbols, numbers, ..).
Like the mainstream political arena, the most accurate explanations don't stick, but the most appealing ones do. The parentheses of Lisp's "function within the tuple" application disappear in the same way that other languages' function-before-the-tuple parenthesis disappear - it's not particularly noteworthy. "Don't even see the parenthesis" is talking past the real objection, which is that the depth of parenthesis in every other language does not matter - ie (expr) is equivalent to ((expr)). Whereas in Lisp they also mean another level of application.
I think an interesting synthesis is Haskell, where function calls are simply juxtaposition. Parenthesis are just grouping like most languages, but it ends up feeling quite Lispy.
> most of your examples would not be considered expressions in the given language.
So that's a piece of cognitive load that you have to carry to know when the parentheses are on an expression, and do not change the meaning if compounded, versus when they are around something else where they may not be removed or compounded.
In Lisp, everything is an expression, and no there is no willy-nilly removal of nesting or compounding of nesting. That's less to remember.
Even fragments of forms are expressions, according to ANSI CL glossary terminology. If we have (let ((a b)) ...) then a, b, (a b), ((a b)) and let are all expressions. With the exception of b, what they are not is forms: expressions presented for evaluation.
> Ultimately this argument is anti-productive nitpicking.
Perhaps you know more of kazinator's history than I do, but that HN account wasn't even created until 2014, so saying kazinator is the one who started this very old argument requires some extra evidence.
I was referring to kazinator's specific argument rooted in languages using parenthesis for things besides expression grouping. I didn't see how that language-lawyering affected my overall point.
FWIW "in Lisp [parenthesis] also mean another level of application" is also technically incorrect (nesting is not always application), but I think it gets the actual point across better than being more abstract.
Parenthesized sexprs are easy to parse (by both machines and humans) and Lisp text editors already have many convenient ways to work with them. There are though some interesting alternatives such as sweet-expressions[1] and wisp[2], but not too many people care about these.
I think the appeal of the syntax for those who get used to it is the regularity, like you said.
The advantage of the regularity isn't its human readability, but its ability to macro, no?
What I'd like to see is better tools for reading and editing such a regular syntax. Probably I should just learn emacs, but I'm thinking someone could make a more intuitive structured editor for LISP syntax. No need to mush around blobs of text when everything is nested lists.
> The advantage of the regularity isn't its human readability, but its ability to macro, no?
This.
You can write macros for less regular languages, but there's always additional friction involved. At some point, it comes down to whether you think LISP is a "programmable programming language."
If you do, macros are a core part of the paradigm, and s-exprs make macros easy to work with.
I would guess, based on the second and third sentences of the article, that the author agrees that this is the primary motivation:
> If you already love s-expressions then lisp-flavored languages will make it nicer when you need to build on existing platforms. In case the target language does not support advanced features like macros and REPL-driven development, these can often be easily added by using the s-expressions layer.
To the comment about "parenthesis-laden syntax", I find that, if I actually count the characters, my Java code tends to have just as many parens as my Clojure code. I suspect that there's just a tendency, if all you've ever known is algol-style syntax, to hyper-fixate on lparens that appear to the left of the function name. I think maybe the only programmers who get to criticize others for overuse of parenthesis are Forth, ML, and Haskell programmers.
At the very least that is more readable due to the indents and the extra syntax. Depending on what language you're using, those different common groups of tokens do communicate context, whereas a dozen right-parens on a single line really don't.
For me personally the regularity is definitely a plus. Especially combined with an editor like paredit or smartparens it becomes very easy to move entire sections of code around.
It's not about syntax. It's about code being data and vice versa.
> Syntax, interestingly, complects meaning and order often in a very unidirectional way. Professor Sussman made the great point about data versus syntax, and it's super true. I don't care how many you really love the syntax of your favorite language. It's inferior to data in every way.
I'm not even criticizing, most of these are hobby projects and you can code how you like. I just think it's funny how hard Lisp clings onto the parenthesis thing while claiming the parenthesis thing doesn't matter.