A language will not succeed without a good name. I have recently invented a very good name and now I am looking for a suitable language.
— Donald Knuth
Louis Reasoner is developing a new computer language. I'm letting him write this post.
“I have already done the most important part: the name of my language is Reason.
“The second most important thing is to come up with a trope. This will enable me to defend my language decisions with a pithy reply and call it a design philosophy. My trope is ‘reasonableness’. Reason will adhere to the philosophy of reasonableness. Anything in my language is, by definition, reasonable. Anything omitted is naturally unreasonable. Here is some more design philosophy:
- Small is more reasonable than big.
- Fast is more reasonable than slow.
- Useful is more reasonable than useless.
- Good is more reasonable than bad.
- etc., etc., etc....
“After the name and the self-styled philosophy, the next important thing is the syntax. The syntax of Reason is complicated, but reasonable. Bear with me. Although it might be a bit difficult to explain, it is, after sufficient practice, natural to use.
“Reason borrows heavily from Lisp and Scheme. Most of the programming in Reason is done in ‘Lisp’ mode. Lisp mode is exactly what you think it would be: you write programs just like you would in Lisp, but with a few modifications to make things more reasonable.
- Prefix notation for everything by default, with these exceptions:
- Infix notation for arithmetic. — Let's just capitulate on this one. Operator precedence will be fleshed out later.
- Excess parenthesis are ignored where it is unambiguous. You can pretty much always add parenthesis to make something clearer or to override operator precedence.
- Function calls have the operator on the outside of the parenthesis. Not only is this more natural, it avoids weird interactions with operator precedence. Arguments are separated by commas.
- Postfix notation for post-increment and post-decrement. — I just like these.
- No ‘special’ forms. We get rid of
define— Lisp code tends to creep towards the right margin. Removing internal definitions makes the code ‘flatter’ and therefore easier to read. (Besides, it's hard to efficiently compile internal definitions.)
begin— No good reason to include it.
cond— Too many parenthesis.
let— Again, too many parenthesis.
lambda— This is just too advanced. Mere mortals can define a named procedure like anyone else would.
letrec— As if
lambdawasn't confusing enough! Who comes up with this stuff?
quote— Too confusing. Actually, I wanted to leave
quotein, but with infix and postfix in the mix I couldn't figure out where the quotation ended. I decided to punt.
- Assignment is allowed. This is technically a ‘special form’, but it is so useful that I had to leave it in.
“In order to radically simplify Lisp mode I had to introduce ‘Program’ mode. Program mode is more imperative than Lisp mode, so I tried to reduce the functionality and power of Program mode so that people would favor Lisp mode. Program mode has these features:
- Special forms — Flow control, variable declaration and binding, conditionals, etc. are available in Program mode.
- No artificially rigid syntax — Program mode is not really infix, prefix, or postfix. Each construct defines its own syntax. This improves readability for the built-in special forms. For example, the
ifconstruct can have a traditional
elseclause rather than just having two or three subconstructs like in Lisp.
- No user-defined special forms — The user doesn't have to memorize any additional special forms beyond the built-in ones.
- No arbitrary nesting — In Program mode, you can only nest a construct if the enclosing construct permits it. There is nesting, it is just controlled.
- Concatenation for a means of combination — Lisp mode is obviously recursively evaluated. This isn't needed in Program mode because arbitrary nesting is disallowed. Instead, user constructs in Program mode are built by concatenation of Program mode primitives.
- Easy switching to Lisp mode — You can always concatenate a Lisp mode construct with a Program mode construct. Originally, I didn't want to do this, but I ended up duplicating a lot of the Lisp mode functionality. By allowing the programmer to switch to Lisp mode pretty much whenever he wants, I avoided having to duplicate a lot of code.
“I could go on for hours about how variables are looked up, but I don't want to bore everyone. I would like some feedback about my ideas so far, though.
How about it? Would any readers care to critique the design of Reason?