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

It would have to have some notation for parse trees, and if that wasn't s-expressions, it would probably be something less convenient, not more.


I had a sneaking suspicion that that was the case.

This reminds me of something that an Associate Professor at Ohio State said when I was presenting on a mathematical tool that I was (and am) implementing. He couldn't remember the order of operations, so he was having trouble parsing the statement:

(forall x, y in Z)(x >= y AND x <= y ==> x = y)

That led him to ask why should I not just include the unnecessary parens, i.e. ((x >= y AND x <= y) ==> x = y), which then led to the question of where to stop adding parentheses. Finally, he recalled talking to another professor who made the case that having rules for order of operations is a bad idea (because those rules have to be memorized), and why not just parenthesize everything? I pointed out, of course, that he was almost exactly describing Lisp.

That thought, however, led me to consider the idea of making order of operations always evaluate left-to-right, except for parenthesized expressions, which would be evaluated first (in the same manner). Leveraging this idea, perhaps it would be possible to escape the hold of exclusively using s-expressions?

My main goal would be to write a general-purpose language which could be used for writing any other language by using the macro facilities, instead of being forced to write Lisp-like languages as appears to be the case with Lisp. Of course, maybe to get that general, you may as well simply use lex and yacc to write a compiler.

Well, anyways, these are mostly just ramblings, and I'm glad to see that others are interested in this idea.


"That thought, however, led me to consider the idea of making order of operations always evaluate left-to-right"

Smalltalk does something similar. In Smalltalk, any infix operator is just a binary message send, and they're parsed left to right. So for example, 12 + 6 / 3 results in 6 instead of 14. This result seems perfectly natural to most Smalltalkers, but it drives me nuts.

Personally, I think it's important to consider the audience when designing a programming language (or anything, really). Operator precedence is totally illogical and adds lots of unnecessary complexity - but it's drilled into people's heads from elementary school onwards. It's like Qwerty keyboards, American date formats, and English spelling. In most cases, though, it's better to work with people's illogical expectations than to say "No, you're wrong, here's a better way." Perhaps that's why Lisp never caught on.


"In most cases, though, it's better to work with people's illogical expectations.... Perhaps that's why Lisp never caught on."

I appreciate the insight here. I think that if the goal is to create a general-purpose programming language for consumption by the average population, it might be better to meet the expectations of the average person. I'm not saying that it needs to be C-like necessarily, but I think that you're right that things like order of operations and other expectations should probably be properly preserved, at least for mathematical operations.

I also realized that my approach was still wrong. If the goal is to be able to build any programming language, the left-to-right approach would already be limited to building a language which evaluates from left-to-right. So it seems that I still have work to do in order to figure out how best to design a language which is able to look like whatever the user desires it to.

One possibility is to sacrifice ease of macro-writing for making other areas of the language more consistent (but not Lisp-like). That is, I would like to keep the expressive power of macros high (even if it involves modifying the read table in some way) while keeping the language intuitive for a beginner. This would likely make it a bit more difficult to write macros, but by the time you are using macros a lot, you are probably a bit more advanced, anyways.

I'm thinking that there has to be some kind of grammar theory that I can leverage here, where the programmer could actually modify the language's parser in the program while maintaining consistency and lack of ambiguity, or being alerted to the potential ambiguity in case they fail to.

In any case, I am quite convinced that Lisp is probably one of the most ideal languages. This means that my hypothetical language may be an example of the phenomenon pg describes, where the best languages are those which are designed for use by the designer, and languages like Java and Cobol are the result of designing for others. I would like to hope that's not the case here, since I'm approaching this with a use-case in mind: to design a language which can be used to design any other language.


But, of course, you don't have to have code files full of parens in order to have s-expressions. Alternative syntaxes have never taken hold in the Lisp world, which may mean they just offer nothing to an experienced Lisp hacker, but they're certainly not impossible.

You can have user-definable infix operators; Haskell has them and uses them to good effect. (The way Haskell does it, you can't have identifiers composed of both letters and operator characters, which Lisp people like to do, but I think we can safely treat that as a matter of taste.) You pick a symbol, say ~, and assign it a precedence and left- or right-associativity:

infixr 3 ~

infixl 7 .!.

Now (x ~ y .!. z) is parsed as ((~) x ((.!.) y z)), where (~) is the Haskell way of making the ~ operator as a prefix function. Haskell also lets you use a prefix function as an infix operator, by putting backquotes around it.

If you want to apply this in Lisp, there is the issue that (foo) means something else than foo; I would like to allow (foo x + bar y) to mean ((+) (foo x) (bar y)), but I wouldn't want (x + y) to mean ((+) (x) (y)). My solution would be that a single value is parsed as just a value, but multiple values next to each other is a function call: (foo x + y) is ((+) (foo x) y), to call y without parameters you have to write (foo x + (y)).

This leaves you with the parantheses for control structures and the like. If you like layout-based languages, you can adopt the rule that "expression + colon + newline + indented expression 1 + indented expression 2 + ..." is parsed as "expression (indented expression 1) (indented expression 2) ...".

Some examples of code from On Lisp formatted like this:

http://himalia.it.jyu.fi/~benja/2007/layoutedlisp.txt

Of course, it still looks like Lisp, with less parens.


That's definitely true in terms of defmacro and syntax-case. However, I do think with some effort the scripting-language community could come up with something almost as powerful as syntax-rules from R5RS, thus catching up to where the Scheme community was in 1991. With syntax-rules the person writing the macro does not have to explicitly deal with the parse tree.




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

Search: