9 ms·
I know at first it looks confusing, but the lisp syntax is pretty much the best. I can teach it to someone in 1 minute: (<function or macro name> arg1 arg2 ...
by didibus 9y ago
I know at first it looks confusing, but the lisp syntax is pretty much the best. I can teach it to someone in 1 minute:
(<function or macro name> arg1 arg2 ...)
That's it. This is 100% of the syntax.
If dealing with a function, the evaluation will always be arguments from left to right are evaluated first, and then the function is called with the result of evaluating the args. This is 95% of the cases.
If dealing with a macro, go read the documentation for it, because every macro is a DSL, and evaluation can happen in different ways. This is the 5% case.
All the complexity of learning a lisp comes from knowing more functions, what they do and how to use them, and learning each macro's DSL.
Can this syntax be improved on, I'm not so sure. Clojure added some special syntax for some more literals, such as [] for vectors, {} for map, etc. And I do think in one way they help, but in others they hurt.
Maybe adding something that distinguishes a macro from a function, but once you know the names of them, the name is enough to know.
Maybe make it so there is a more visible demarcation between the function/macro name and the arguments. Not sure how though.
All that to say, if you give the ayntax a good chance, like 2 to 3 months of 40h a week for your brain to more clearly see where the functions start and end, I'm sure you'll like it.
- int_19h 9y agoThat something is simple and easy to explain doesn't necessarily mean that it's the best. Simplicity can hurt readability, for example, by utilizing too few distinctive visual patterns - fewer than human brain can easily distinguish while scanning code - and then having to reuse those same patterns for different things, making it necessary to pay more attention to finer details of the code to understand what it does. To give an analogy, imagine that we replaced all our punctuation with S-expressions. It would be simpler in conceptual sense, but do you think you could read such text faster than the one that distinguishes between commas, periods, question marks etc?
- lisper 9y agoThat's the wrong comparison. S-expression don't compete with natural language any more than C does. S-expressions compete with JSon and XML. And IMHO they win hands-down.
- int_19h 9y agoI didn't claim that S-exprs compete with natural languages. I'm saying that C is to S-exprs is like natural language is to an artificial language where all punctuation is replaced by a single symbol + words.
- rayiner 9y agoEnglish prose, which presumably is very readable, uses very little in the way of visual patterns. Spaces between words, periods between sentences, line breaks between paragraphs, and a tiny handful of punctuation characters are enough to write an entire novel. Almost all meaning in English is represented by word order rather than punctuation or visual patterns.
- traviscj 9y agoPeople often reply to the word and phrases, rather than ideas, that they noticed in a particular email, rather than the meaning of the whole email.
- barrkel 9y agoProse is full of redundancy. You can skip lots of words and still get the gist of what's going on. The words themselves are also full of redundancies - rmmbr prse wrttn wth mssng vwls?
- int_19h 9y agoExactly like a programming language, then. But I disagree that all the things that you've listed are "little". Again, try ditching all punctuation, and see how much your reading speed suffers - even though it's the same words. Just like PLs, natural language has to be parsed to determine word and sentence boundaries, before you can understand their semantic meaning. It's that parsing speed that spaces between words, periods between sentences etc affect. And similarly with PL syntax, it's what all those ()[]{} things do.
- TeMPOraL 9y agoI disagree. IMO it's just about what you've learned before. Note that parsing natural language isn't obvious until you learn to read - a task on which you spend years of your life. I'd argue Lisp is no less readable than C for people who haven't seen a programming language before. It's just more likely your first language will be C-like rather than Lisp-like, and this colors your expectations. Funny things, people in our industry deal with Lisp-like syntax all the time. Consider HTML or XML. If you grok how they work, you'll also understand S-expressions. Except S-exps have less clutter.
- int_19h 9y agoXML is not like S-expr in the sense that I'm referring to - quite the opposite, in fact. In XML, special syntax - <> - is used to visually distinguish what in S-expr is a head item from the rest of them. Furthermore, there's a big visual difference between attributes and child elements, as well. Although once you get to a higher level of structure, XML shows similar deficiencies to S-exprs. For example, consider XSLT - that's a programming language that uses XML as syntax for both its language constructs, and its data. There are good things and bad things about XSLT, but I have never heard anyone claim that readability is its strong point. In contrast, XQuery - which uses its own Algol-style syntax for language primitives, and only uses XML-like syntax for inline data, is much more readable.
- mschaef 9y ago> Simplicity can hurt readability, for example, by utilizing too few distinctive visual patterns - fewer than human brain can easily distinguish while scanning code There's a bit of a tradeoff. I tend to agree with you that there is at least an initial readability hit when looking at most Lisp code. However, that's something that can be managed with a bit of experience reading/writing the syntax and some care taken with the way you write the code. The benefit of the Lisp syntax comes in that its regularity makes it easier to make tools that manipulate it in higher order fashions. (Paredit mode and macros being two examples that immediately come to mind.) Not only does the syntax make it easier to write those tools, the syntax makes it easier for developers in the moment to understand what those tools actually mean and how they operate on code. The trouble with all this for Lisp is that the costs are immediately evident, but the benefits all accrue on a longer time scale. It's a style of language that rewards patience and long term investment in a world that does not necessarily favor either.
- int_19h 9y agoIMO, the ease of manipulating Lisp code comes from that code being internally represented as a tree. But that doesn't mean that the syntactic representation has to be so closely mapped to that underlying tree. Syntactic sugar is good! In fact, it's so good that even Lisp has some - you still write '(1 2), even though your macro will see (quote 1 2). My point is, essentially, that raw S-exprs, or even S-exprs with the usual Lisp extensions, are too "bitter" - there's not enough syntactic sugar there to have them go down smoothly. For a very extreme opposite example, consider R. Under the hood, any R program is represented as S-expr style tree (the corresponding data type is "call" - but it's basically just a linked list of arbitrary objects, including other call objects, and its interpretation is exactly like a Lisp S-expr - first item is what we're invoking, the rest are arguments). Then on top of that they have created a C-style syntax. But that syntax is pure syntactic sugar - there's an exact one-way mapping from it to the actual call tree, and there's a canonical back-mapping as well. And you can skip the syntax and write everything in pure calls if you really wanted to. Now, I'm not claiming that this is the sweet spot. But I'm pretty sure that S-exprs aren't it, either. It feels like there can be some middle ground, where the original tree structure is still fairly recognizable, but also with enough sugar that common patterns (e.g. variable bindings, function definitions, conditionals etc) are easy to parse visually.
- didibus 9y agoS-expressions are more of a grammar, you'd need to change the English grammar to something more like it, specifically make the action first. Send money to John's account -> (send-to (account-of "John") money) Find all empty boxes in the warehouse -> (find-in warehouse empty boxes) If Bob is home tomorrow, tell him John was looking for him. -> (if (is-home bob tomorrow) (tell bob (fn [him] (was-looking-for him bob)))) Now you'd have to define a lot of those arguments, and the implementation of these functions would be complex, to interpret all the relational rules of natural English language. But I feel this would be s-expressions applied to english. Things would be grouped in parenthesis, with the action first, and the set of things involved in the action following. Conditions would come first, different tense would be different functions, subject and complement would follow as arguments, and actions can involve other actions by passing them as arguments. Now on the subject of readability, I think you're right. Spacing, font, whitespace all helps readability, and maybe the syntax lacks a little in visual separation and organisation, though you can solve most of it with indentation. But I think we must also consider comprehension. Code is more than about reading the text, it's all about understanding the underlying behavior. I think LISP syntax is good for that, in fact, it's much closer to English in that sense. It can have very powerful embedded semantics. But just like English, it requires you learn the definition and rules of a lot of words, or in LISP, functions and macros. That's what people mean when they say LISP syntax is both simple yet powerful. Now it's not easy to learn, just like English isn't, but once you know it, it's much more expressive, and the rules are simple, but build off one another to form complex systems. I think this is actually very close to a natural language in a way.
- kazinator 9y agoS-expressions are less of a grammar. (send-to (account-of "John") money) has a tree structure that is known even if those symbols have no assigned meaning or lexical category. We know that structure by following just the tiny grammar that governs the parentheses and symbols, instead of the huge (and not completely knowable) grammar which governs sentences like "send the money to John's account". Linguists do in fact use parenthesized notation ("labelled brackets") http://www.glottopedia.org/index.php/Labeled_bracketing http://www.glottopedia.org/index.php/Labeled_bracketing This indicates what the syntax is of a sentence, so that parsing according to a grammar is no longer necessary.
- seanmcdirmid 9y agoLisp syntax is like no syntax at all, it's all just direct parse trees. It is unviable without more secondary formatting than syntactic forms since it is really difficult for the eyes to balance parantheses on their own. That LISP-style (non) syntax is successful just goes to show how little syntax really matters (I.e. the null case works), I guess.
- mmalone 9y agoI get what you're saying, but that's a pretty extreme view. Parenthesis are obviously syntax, even if they look similar to the notation used to represent ASTs in other languages. They are minimal syntax, but they're still syntax (also, lisps have `"@' and sometimes {}[]). Just because this is the internet, I'll also disagree with your second point. Lisp programmers use white space and macros to make programs more readable. Despite this, lisp's adoption trails many less powerful languages that offer more intuitive syntax. Since lisp's metaprogramming facilities allow it to effectively simulate pretty much every other style of programming, the only explanation that I can come up with for this situation is that intuitive syntax matters a lot (at least for language adoption).
- seanmcdirmid 9y agoMacros aren't so much syntax as they are semantics (inlined for performance, but we can still think of them as special procedure calls). Lisp has been relatively successful in its various forms, it should get some credit.
- lispm 9y agoMacros serve lots of purposes. One is providing convenient syntax. (loop for i from 10 below 100 step 3 when (evenp i) collect i) Above is using the LOOP macro, which implements a lot of syntax for various ways to LOOP. The syntax description is actually quite long: See the EBNF description of the LOOP macro in the standard: http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm#loop http://www.lispworks.com/documentation/HyperSpec/Body/m_loop... There are other syntactic forms which use more parentheses. For example the DEFCLASS macro. The basic EBNF syntax for DEFCLASS is: defclass class-name ({superclass-name}*) ({slot-specifier}*) [[class-option]] slot-specifier::= slot-name | (slot-name [[slot-option]]) slot-name::= symbol slot-option::= {:reader reader-function-name}* | {:writer writer-function-name}* | {:accessor reader-function-name}* | {:allocation allocation-type} | {:initarg initarg-name}* | {:initform form} | {:type type-specifier} | {:documentation string} function-name::= {symbol | (setf symbol)} class-option::= (:default-initargs . initarg-list) | (:documentation string) | (:metaclass class-name) The DEFCLASS macro implementation will check some of that automatically, but much of the syntax has to be check by the macro in the implementation code. > we can still think of them as special procedure calls That's not a good idea. It's misleading.
- GregBuchholz 9y ago>(<function or macro name> arg1 arg2 ...) >That's it. This is 100% of the syntax. (list '(1 . (#x-A 2.3 |(+ foo bar)| #|4|# #\#)) (1+ '#C(-5/6 +7.s-8)) "(* 9 10)" () #()) ; and then some
- Johnny_Brahms 9y agoWhich fits the grammar. Sure, you are using some literals, but that is an application of the list procedure with 5 arguments.
- Johnny_Brahms 9y agoHaha. I just proved you right. Common lisp apparently has block comments.
- TeMPOraL 9y agoOf course it does. #| this is commented out |#. Comment syntax is usually something "special" in each language anyway.
- Johnny_Brahms 9y agoAnd I didn't know it, hence me thinking there were 5 arguments.
- GregBuchholz 9y agoThat's all one expression, and there are 5 argument to the list procedure: 1.) a list containing three numbers, a symbol, and a character, 2.) a complex number, 3.) a string, 4.) the symbol "NIL", 5.) the empty vector.
- Johnny_Brahms 9y agoI shouldnt have read it a second time on my phone. I was right the first time. :)
- kbp 9y ago> If dealing with a function, the evaluation will always be arguments from left to right are evaluated first, and then the function is called with the result of evaluating the args. This is 95% of the cases. > If dealing with a macro, go read the documentation for it, because every macro is a DSL, and evaluation can happen in different ways. This is the 5% case. Not arguing with your point, but just for fun: CL-USER> (let ((functions 0) (specials 0)) (do-external-symbols (symbol (find-package :cl)) (cond ((or (macro-function symbol) (special-operator-p symbol)) (incf specials)) ((fboundp symbol) (incf functions)))) (/ (* specials 100.0) (+ specials functions))) 15.425532
- pg314 9y ago> If dealing with a function, the evaluation will always be arguments from left to right are evaluated first, and then the function is called with the result of evaluating the args. The order of evaluation depends on the dialect. Common Lisp evaluates the arguments from left to right, but e.g. in Scheme the order of evaluation is deliberately left unspecified.
- didibus 9y agoIn the spec, but I've yet to see an implementation that does not follow left to right order. Do you know of any ?
- pg314 9y agoExercise 4.1 in SICP [1] asks for an implementation that evaluates operands from right to left. :) Other than that, I don't know of any implementations that do. I also don't know of any implementations that guarantee left to right order. Many manuals specifically mention not to rely on the order of evaluation (e.g. Chez Scheme). Since I try to avoid depending on unspecified behavior if I can avoid it, I might not notice when an implementation uses a different evaluation order. I would expect one of the optimising compilers (MIT Scheme, Chez Scheme, Stalin) to be your best bet to find a real implementation with non-left-to-right order. And it might require a specific set of circumstances to trigger, so trivial examples might work ok. And of course, just because current implementations use left to right order, doesn't mean that that can't change in the future. [1] https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.html#%_sec_4.1 https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.htm...
- coldtea 9y ago>I can teach it to someone in 1 minute Teach it, yes, but then you have to spend decades to make people tolerate it.
- TeMPOraL 9y agoIf you find a way to work around human irrationality, you'll win a Nobel prize in more than one domain. :(.
- coldtea 9y agoOnly if you assume that the irrationality is useless, e.g. doesn't have evolutionary advantages. Which I think it does, many.
- TeMPOraL 9y agoThe thing about evolutionary advantages is that things that helped us in pre-agricultural age aren't necessarily so helpful in the so vastly different environment of a technological civilization.
- coldtea 9y agoI'm not so sure, because "not helpful" in the day-to-day experience in the technological civilisation is not the same as not helpful in the long term. E.g. the progress of the technological civilization itself might not even be in our long term advantage as a species (we might think it is, but that's not the same as it being -- e.g. every too developed civilization might collapse over complexity, or kill itself, irrationality or not).
- didibus 9y agoI don't think that's the syntax people find hard. I think its the semantics. The functional way of doing things confuses people. The fact that your program is a single nested chain of function calls I think is what people struggle with most. That and the dynamism. The whole thing just needs time getting used to, because it's unfamiliar.
- stewbrew 9y agoBut then you need x years to teach them all those mini macro languages like loop etc. While I personally have pleasant memories of the time I used lisp, I learned to like languages with some syntax and the support editors and IDEs provide for that languages.