views:

893

answers:

14
+7  Q: 

Fixing Lisp Syntax

Being a newbie to Lisp I'm wondering if the Lisp syntax could be "fixed"?

Some people say the syntax in Lisp is one of its biggest strengths. I don't quite understand this.

Isn't it possible to replace "obvious" parentheses with a combination of white spaces, new lines and indenting? Just like in Python?

It looks to me like parentheses are the most used characters in Lisp code. I'm wondering if that's true - but if it is, isn't this a suggestion, that there is some redundancy in the syntax?

Is there some simple answer to the question - why so many parentheses?

For example:

(defun factorial (x)
    (if (= x 0)
        1
        (* x 
           (factorial (- x 1)))))

Why not:

defun factorial (x)
  if (= x 0)
    1
    * x
      factorial
        - x 1

e.g. close parentheses at the end of line, and always open them on new lines. Only the 1 would be ambiguous - is it 1 or (1) - but we could introduce an exception - single tokens are not "listified".

Could this work?

Edit:

Thank you all! I see now there are some links at the lispin site.

+8  A: 

What you suggest appears to have been implemented in Lispin

cmsjr
Interesting... is the converse true, e.g. is there a variant of Python that uses parentheses instead of indentation?
Jason S
i'm sure there would be one if python were also 50 years old... :)
Attila Lendvai
"is there a variant of Python that uses parenthesis" -- probably. Just look back in history for a simpler variant of Lisp predating Common Lisp. Of course, it will be lacking the large library support modern Python distributions contain.
Aaron
+3  A: 

It could work. It's called Dylan.

Pete Kirkham
Dylan lacks the code is data part.
Rainer Joswig
i'd put it like this instead: "one can try, it's called dylan"... :)
Attila Lendvai
+1  A: 

To answer the question of why:

It's main use as far as i know is readability, so that people who look at your code can decipher it more easily.

Hope it helps.

Cristina
+21  A: 

It's been done lots of times (a < twenty line preprocessor will do wonders). But there is also an advantage to having them explicit. It drives home the parallelism between code and data, and in a way leads you out of the sort of thinking that makes you find them annoying.

You could (for an analogous example) take an object oriented language and remove all the syntactic grouping of methods into classes (so they became, in effect, overloaded functions). This would let you look at it more as you would a straight imperative language, but something would be lost as well.

When you look at lisp you're supposed to think "Everything is a list. Ommm"

(Well, Ok, the "Ommm" is optional).

MarkusQ
+1 for the "Ommm"
Chris Lutz
+3  A: 
Alexander Temerev
this theory sounds nice, but i'm a block kind of guy and i'm most productive in lisp. i even have strong rules how to indent lisp variable declarations, boolean expressions, etc... to help my block-parser when i get back to the code later.
Attila Lendvai
Lisp has a standard indentation style that gives you your blocks. You won't see the parentheses anymore after a short while.
Svante
I don't buy this, I think that any smart person could go between the two with minimal problem.
temp2290
Nice Lisp code has a standard indentation that makes 'blocks' visual. It also relies on a lot of structural conventions and layouts for those. The visual triggers for these conventions need to be learned and they are mostly based on naming conventions using symbols and not on special characters.
Rainer Joswig
+12  A: 

You'll change your mind once you write a couple of macros.

dnolen
THIS answer should be accepted as the answer (though it's pretty terse). Macros are EXACTLY why the parens are so awesome. Given the question was "would removing the parens break lisp?", the answer can be found here.
Matt Curtis
you can have equally powerful macro systems for more complex syntax (see slate as an example), but macros are complex enough using simple lists denoting programs, so very few people bother with powerful macrosystems working on AST's of syntax-rich languages.
Attila Lendvai
@Attila, power and simplicity are not inversely related. Point taken though.
dnolen
Dylan is a paren-free infix Lisp and it still includes macros. Common Lisp as implemented needs its syntax to write macros, but parens aren't inherent to the concept of macros.
Chuck
Lisp macros don't work over s-expressions. S-expressions with parentheses, lists, symbols etc. are only an external representation. Lisp macros work over internal data. How the expressions are externally represented is independent of macros.
Rainer Joswig
@Chuck, I wasn't saying that parens are what make macros possible. @Rainer, you're right. But it seems to me Lisp's insistence on parens for structuring code eases the cognitive load when reasoning about macros.
dnolen
+2  A: 

Even Paul Graham, a vocal advocate for the Lisp family of languages, has removed some parentheses from his own dialect Arc:

Note to Lisp hackers: If you're used to the conventional Lisp cond operator, this if amounts to the same thing, but with fewer parentheses. E.g.

(cond (a b)
      (c d)
      (t e))

becomes

(if a b
    c d
    e)

(from the Arc Tutorial)

Frank Krueger
The problem is that the parentheses provide grouping and that's missing from Graham's IF. With COND I place the cursor between two clauses and press m-t (that's: exchange sexp) and they get exchanged. I can move clause up or down.
Rainer Joswig
@Rainer, my largest Lisp program was a quantum simulator and compiler. Small. So I can't even decide which I prefer. I can, however, say that your "Domain Specific Language" screencast was inspiring. It was a pleasure to see an experienced Lisp hacker at work.
Frank Krueger
@Frank That's for the positive feedback.About 'deciding'. That's part of the 'Lisp experience'. With some experimenting you learn to acquire some 'taste' what looks good AND feels good. 'Feels' means, what is easy to manipulate with the text editor AND the Lisp system. Code is data. Data is code.
Rainer Joswig
this arc example is a great characerisation of why i don't like arc: playing with lisp's syntax will not yield anything interesting, becuase one of the point of lisp is exactly its non-syntax-ness. small changes to the syntax will not characterize a dialect at all, it'll merely yield a new one.
Attila Lendvai
Sure Lisp has syntax, lots. Syntax is about the structure of valid expressions in a language. Check out the syntax for the Common Lisp constructs in the HyperSpec - it is defined on top of s-expressions. Some is built-in, some is implemented via macros.Lisp is for playing with syntax.
Rainer Joswig
A: 

Reading through the links, I found this one - Indentation-sensitive syntax - there is also Guile module, that implements this syntax, so one could directly try it.

A quite promising Lisp dialect (Arc) could be found here. (I guess one should first some real code see how it feels)

siddhadev
arc is not promising, it's just another one...
Attila Lendvai
+10  A: 

"Perhaps this process should be regarded as a rite of passage for Lisp hackers."

-- Steele and Gabriel, "The Evolution of Lisp", 1993

Ken
+7  A: 

Several times I've compared Lisp code and equivalent code in other languages. Lisp code has more parens, but if you count all grouping characters []{}() in other languages, Lisp has fewer parens than all these. It's not more verbose: it's more consistent!

When seen from this point of view, the "problem" is simply that Lisp uses one type of construct (lists) for everything. And this is the basis for its macros, its object system, a couple of its most powerful looping constructs, and so on. What you see as a minor style issue (would brackets look cooler? probably) is actually a sign of language power.

That said, Lisp is all about giving power to the programmer. If you want, write your own dialect that lets you do this. Lisp (unlike some languages I could mention!) is all about programmer power, so use it. If you can make it work, maybe it'll take off. I don't think it will, but there's nothing to stop you from trying, and you'll learn a lot either way.

Ken
+5  A: 

The point of lisp "syntax" is its non-existence. An s-expression is a tree of identities, where the tree structure is denoted by parens (and indentation). It's worth noting that sexps were meant to be a low-level representation only, but people ended up liking it more and kept using it.

What an expression means to the execution engine is incredibly flexible in lisp and it's also context sensitive.

In other languages, the level of context sensitivity is much lower and the set of building blocks you can use to build your own abstractions is much less freely extensible. Therefore, special syntax denoting the few given constructs is fitting the picture.

In lisp, I can change the meaning of everything, even in a context sensitive manner. Having special syntax for a few predefined constructs would be silly because I may end up using my own 'if', or my own specialized closures, etc.. What if my new 'if' needs 4 arguments (e.g. to group certain if's of a program and tell some groups to always fail or succeed in certain situations)? How should I extend the syntax of the predefined 'if'? It's much easier to resort to the AST (sexps), but then why bother with special syntax at all?

Also note that using an editor like emacs makes it very easy to edit such a tree in a structured way. For example, having a key to transpose two nodes in a tree is equally useful to swap variable declarations and to swap two statements in a program block (hint: that's why the "extra" parens are useful in let, cond, etc.).

So, that's the reasoning why the non-syntax of lisp is so appealing to many people who got used to the idea of extending the language instead of bending the problem to fit a predefined set of tools... but it doesn't mean that syntax sugar is not used for user-given constructs!

Some examples of user defined syntax that we use:

  • cl-syntax-sugar - the most notable extension is the [] parens used for tiny closures where you don't want to name the closure's variables
  • cl-quasi-quote - most notably the <xml > syntax to inline the xhtml generation in lisp code (please note that this syntax is provided by a user library, and it can be enabled in a context sensitive manner)
Attila Lendvai
Lisp usually has a two-stage syntax. Data syntax with S-expressions and program syntax over s-expressions. Both are syntax - which is concerned with the structure of valid 'sentences' (programs) in language (Lisp).
Rainer Joswig
A: 

My personal opinion on this is: don't use newlines and indentation as "implicit" separators (I also don't like implicit grouping by operator precedence, but that is a different, although related topic).

Example: Is this valid Python? Does it do what you expect?

if foo < 0 :
    bar
  else :
    baz
quuz

I have a little proposal: we could use a preprocessor to indent Python code automatically, by putting special characters into the code that tell it where a statement begins and ends. How about parentheses for this?

Svante
A: 

You could take a look at Clojure. Lesser parentheses but more syntax to remember.

Abhijith
A: 

I've tried out and written couple of syntaxes that rely on indentation. At the best results the whole syntax has changed it's nature and therefore the language has turned from one to another. Good indentation-based syntax isn't anything near lisp anymore.

The trouble of giving syntactic meaning for indentation doesn't rise from the idiots and \t vs. whitespace debating. Tokenizing is neither a trouble since reading newlines and spaces shouldn't be harder than anything else. The hardest thing is to determine what indentation should mean where it appears, and how to add meaning to it without making too complicated syntax for the language.

I am starting to consider original lisp style syntax is after all better when you minimize the amount of parenthesis with some clever programming. This can be done, not so easily in current lisp implementations, but in future lisp implementations it can be done easier. It's fast and simple to parse when there's only couple of rules you have to tokenize, and nearly no parsing at all.

Cheery