Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I agree that s-expressions are not necessarily always the best choice.

But your argument about this having to do with what compiler one is using doesn't make sense to me. S-expressions are easily parseable in virtually any language. S-expressions are always going to be one short-cut around the problem of deciding what syntax your language should have (my object is this short-cut may not help your language in the end - your S-expression language will be considered less-than-understandable by the same reasonably large group of people who consider LISP less-than-understandable).

For example, Google give this complete lisp interpreter in c:

http://www.umcs.maine.edu/~chaitin/lisp.c

Haskell may have facilities that make parsing any language reasonably easy, sure. But I have news, parsing language is easy once you learn a bit anyway.



Ok, let me clarify this for you. Warning: this is going to be rather Haskell centric. My argument isn't really about the syntax of the target language at all but the internal program representation in the compiler/interpreter.

Representing tree structures like abstract syntax trees is really easy and convenient in Haskell. The traditional example, curried λ-calculus with integers looks something like this:

    data Expr =
        Constant Int |
        Identifier String |
        Application Expr Expr |
        Lambda String Expr
Haskell makes it easy to handle such tree structures using pattern matching. Of course it is at least as easy to represent s-expressions with a similar tree structure. However, there are multiple benefits of using a tree structure like that, for example you will get a compiler warning if you forget to handle one or more of the possible cases in a non-exhaustive pattern match.

It is also easier to write a parser and pretty printer (using Parsec and Pretty combinators) to convert that tree structure to/from human readable/writable strings (ie. program source code) than it is to convert s-expressions to such a tree structure.

So while using s-expressions is certainly possible, in a nicely typed language like Haskell, it will be nicer to have a proper syntax tree data structure and the advantages of s-expressions are not really there unless you are writing an interpreter for a homoiconic language like Lisp or Prolog.

The way I usually start a programming language project (I do lots of those) is writing "programs" by specifying syntax trees for test cases in Haskell using literals and then running them through the interpreter/compiler/type checker. Only when I have something that actually works (and developing and debugging by writing the tree structures becomes unwieldy), I start thinking about the syntax and write the parser and pretty printer.

So if you're using a host language other than Lisp to implement your compiler/interpreter and your source language isn't homoiconic, using s-expressions as your internal program representation might end up being unwieldy. The syntax of your source language is pretty much irrelevant in this discussion, but writing a proper parser to produce tree structure might make sense rather than reading s-expressions.

Does my explanation make sense to you? If you have any questions, don't hesitate to ask.

Here's a few of my toy language projects for your enjoyment, you'll find examples of the things discussed above there:

https://github.com/rikusalminen/funfun LLVM compiler for a toy functional programming language (with type inference!)

https://github.com/rikusalminen/slolog Prolog-esque logic programming language


It is also easier to write a parser and pretty printer (using Parsec and Pretty combinators) to convert that tree structure to/from human readable/writable strings (ie. program source code) than it is to convert s-expressions to such a tree structure.

Well, parsing S-expressions is easy in most language. Unless somehow parsing an S-expression is hard in Haskell, it doesn't matter whether parsing easier. Normally, it just means both S-expressions and generic parsing is easy.

Your overall argument could better be written "S-expressions aren't part of the particular syntax transformation method I use." OK, sure.

An S-expression based interpreter is still pretty darned easy to write (unless Haskell has weird barriers that other language don't have, if so, it doesn't reflect well on Haskell).


> Well, parsing S-expressions is easy in most language. Unless somehow parsing an S-expression is hard in Haskell, it doesn't matter whether parsing easier. Normally, it just means both S-expressions and generic parsing is easy.

> An S-expression based interpreter is still pretty darned easy to write (unless Haskell has weird barriers that other language don't have, if so, it doesn't reflect well on Haskell).

Oh, I knew I was too Haskell-centric in my answer because you missed my point entirely.

You can write an S-expression parser in Haskell, it's just as easy as writing it in any other language. But this wasn't the point at all.

Using S-expressions as the program internal representation just doesn't make sense in Haskell. You can do it and you should do it if implementing a Lisp dialect or other homoiconic language, but in general, it's a lot better to build a proper tree structure. The major advantage of s-expressions in the Lisp world is not really the syntax, but it is an universal tree structure.

Same thing applies if your host language isn't Lisp and you have a proper abstract syntax tree structure (either enums + unions or a class hierarchy or whatever). You can parse s-expressions but you need an extra step to get into the tree structure you're going to be using internally.

Your impression that S-expressions are hard in Haskell is just incorrect, my point was that there are better facilities for tree structures and parsing than S-expressions are.

As I said first thing in the earlier post... my argument isn't really about syntax, it's about the internal program representation.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: