13 ms·
My unsolicited, biased advice: use s-expressions. Don't trigger a parse simply to compute with the sums of products and integers [0]. If you can think of someth
by agentultra 13y ago
My unsolicited, biased advice: use s-expressions. Don't trigger a parse simply to compute with the sums of products and integers [0]. If you can think of something better than s-expressions use that.
Also, read http://this-plt-life.tumblr.com/ http://this-plt-life.tumblr.com/ and don't take yourself too seriously. Stand on the shoulders of giants and continue reaching for the sky. Languages are super fun.
[0] http://www.infoq.com/interviews/mccarthy-elephant-2000 http://www.infoq.com/interviews/mccarthy-elephant-2000
- qznc 13y agoWell, infix math is very nice and easy on the other hand. Also, range and index syntax like Python is nice.
- sillysaurus2 13y agoInfix math is only nice because you've been trained to believe it's nice.
- dllthomas 13y agoWhile I am pretty sure this is entirely true, it's crazy not to recognize that you're producing a language where basically everyone has been thusly trained since kindergarten.
- stormbrew 13y agoI question its truthiness. It's not as if there's some shadowy cabal conspiring to force people to put operators in the middle, we developed the infix notation over a long period of time and it seems likely there are good, though possibly not entirely logical, reasons for it. We humans have funny brains, after all. And if you really want to dive down that rabbit hole I think you have to establish that prefix is better than suffix as well. I'm somewhat dubious of even this claim, since I find suffix easier to reason about. But maybe that's just me.
- dllthomas 13y agoI think path dependence is plenty to force us into behavioral patterns where alternatives aren't more than marginally better. There may be ways in which infix is genuinely better (I'd conjecture perhaps flexibility of ordering permitting more communication, in terms of emphasis and structure, in the same formula), but I would stand strongly by the notion that the primary reason we respond that it's "nice" is familiarity. This is particularly recalling the trouble some of my peers had with order of operations, but I think if it was flipped and we'd spent a decade dealing with prefix notation before being confronted with infix, while we might find things with prefix notation to struggle with as children we would find prefix "nice" having struggled. I think looking at pros and cons (in the abstract and in people's heads) of prefix vs. suffix could be interesting. What I like about suffix is that you can treat it as a stack. What I like about prefix is that I know what kind of node I'm building as I consider the arguments. I've not done enough of either to have much opinion on which matters more (some lisp, some rpn calculators, but not enough). I certainly wasn't agitating for prefix (in particular) above.
- breuleux 13y agoOne argument for infix is that it minimizes the distance between the salient token (the verb) and its arguments. When you see "a := b", the ":=" serves as a convenient visual anchor to check the variable name (to its left) or its value (to its right). Note that English itself is an infix language: "Bob likes Clara" (SVO, infix), rather than "Likes Bob Clara" (VSO, prefix) or "Bob Clara likes" (SOV, suffix). A cursory search tells me SVO and SOV cover 75% of all languages. It would be interesting to see if people speaking SOV languages would prefer suffix notation. I would expect common patterns in (unrelated) world languages to loosely mirror natural dispositions towards syntax. In practice, that's probably a hodge podge of prefix, suffix and infix depending on whether you're dealing with verbs, connectives, prepositions, etc.
- stormbrew 13y agoSomewhat tangentially, I wonder if some of the appeal of object oriented languages is that they usually explicitly mimic SVO. myArray.find(2) is closer to real natural language than array_find(myArray, 2).
- mikeash 13y agoThat strikes me as being pretty much the same as saying that English is only nice because you've been trained to believe it's nice, and why not write your language in Klingon instead? When you're dealing with human interfaces, existing convention counts enormously.
- Arelius 13y ago> That strikes me as being pretty much the same as saying that English is only nice because you've been trained to believe it's nice, and why not write your language in Klingon instead? There is a reason we don't program in English, and keep inventing new programming languages. English is poor and ill suited for the problem, even though it has enormous existing convention.
- mikeash 13y agoNor do we program in infix math. But we write languages that use both infix math and bits of English where appropriate, because taking advantage of existing conventions helps a great deal.
- kerkeslager 13y agoWe don't just use English to write software, but we DO use convention from English. In some sense, keywords like "f" and "j" are better-suited for expressing conditionals and loops because they are shorter to read and type. But I'm sure glad language designers settled on "if" and "for". The reason they did that is convention.
- acjohnson55 13y agoThat's not really true. Infix math definitely has its place, particularly for sequences of operations, like monadic chains. It's kind of nice having the input and output on the extremes of the expression, with the parameters attached to the operators, as opposed to prefix notation, which puts the input inside layers of nesting.
- pseut 13y agoI love this. Write an integral with infix notation. :)
- peterwoo 13y ago(0, 1) $ (\x -> x*x)
- andrewflnr 13y agoI might actually put the limits after the integral sign. Then it makes an indefinite integral look like a partially-applied function just waiting for a tuple of limits to make it a definite integral. That might get hairy for iterated integrals, besides being highly unconventional.
- peterwoo 13y agoYeah, that would seem to be more practical with respect to currying (and perhaps dynamic dispatch). I was just trying to make it look as similar as possible to the Leibniz notation. :)
- anaphor 13y agoThis is a nice compromise between pure s-expression syntax and something a little friendlier: http://shriram.github.io/p4p/ http://shriram.github.io/p4p/ (basic idea, get rid of the implicit 'begin' form from everything)
- roryokane 13y agoAnother syntax that tries to make S-expressions friendlier is “sweet-expressions”: http://readable.sourceforge.net/ http://readable.sourceforge.net/. Its main change is using Python-like indentation to allow you to remove a lot of parentheses. It is backwards compatible with S-expressions.
- James_Duval 13y agoI find that much less readable than S-expressions. Well-formatted S-expressions actually make it pretty fast for me to find what I'm looking for in code, probably faster than in C-like languages - and I mostly use languages which are more-or-less C-like.
- munificent 13y agoBut parsers are easy to write and unfriendly syntax will completely kill a nascent language's adoption. If you're aiming for users that like s-exprs, then by all means use them. Otherwise, try to stick to a syntax roughly similar to one familiar to the users you're targeting.
- cousin_it 13y agoAs a user of programming languages, I don't care about s-expr vs infix syntax, but I do care about the amount of semantic innovation that went into a language (as in I refuse to learn any language whose main contribution is syntactic), and sadly it seems that wasting time on syntax distracts many PL creators from the semantic poverty of their creations.
- johnbender 13y agoThis was my primary frustration with the article. It notes that the "bulk" of the work in building a programming language is in defining the semantics but devotes absolutely no space to the process, tools, and tradition. A programming language is the semantics and without a strong notion of those semantics and the interactions you end up with confusion and difficulty. For an example one need look no further than Ruby's "implementation as specification" crazyness. I won't go as far as to say that all language creators should adopt operational semantics when building a language, but if you're serious about it then you should at least investigate the process.
- WalterBright 13y agoI deliberately tried to avoid topics that are well-covered elsewhere.
- dllthomas 13y agoAppropriate, but can you point us at some of those elsewheres?
- joe_the_user 13y agoBecause the world needs another version of LISP...? Wait, if you say "just don't do it, learn LISP instead and just customize your stuff", well that is good advice, OK. Still, learning real language construction tools is a cool thing. It's mainly cool in the long, miserable, thankless journey way the article describes yes. But beautiful still. Nice syntax the way human like to read has had a long, successful history. But LISP has had it's moments too...
- mattfenwick 13y agoI'd just like to point out that s-expressions are not the same as Lisp. Rather, they are orthogonal. Using s-expressions for concrete syntax does not say anything at all about the semantics of your language. This also means that there can be multiple concrete syntaxes for a language: e.g. for Python, you can use the standard syntax, but you could also use s-expressions, without changing the semantics one bit.
- agentultra 13y agoBut we have to jump through some hoops to convert expressions into statements/expressions (I work a bit on Hy[0] which does exactly this). [0] https://github.com/hylang/hy https://github.com/hylang/hy
- mattfenwick 13y agoYes, that's typically how it works -- at some point, the concrete syntax tree has to be converted to abstract syntax. I wouldn't call it jumping through hoops though. Rather, for me, it's a natural consequence of separation of concerns. I try to build parsers that only know about concrete syntax. A later pass over the CST is responsible for building the AST, which prevents coupling of the parser to the abstract syntax. YMMV. There's more than one way to skin this cat.
- joe_the_user 13y agoOK, s-Expressions are not the same as LISP sure but I don't think you can say they are orthogonal either. They are a key aspect. Sure, you can have a non-LISP s-expression language but the boundary between this and a subdialect of LISP is going to be porous. The strengths and the weaknesses of LISP, as far I can see, come because it is so easy to just create a mini-language, a sub-dialectic to do this and that. I'll assume people know the strengths (and I'm the one say them most eloquently), I'd mention simplicity, flexibility, recursion, homoiconity, etc. I'd say the weaknesses "easy wheel reinventing", which has resulted in many half-formed wheels and few canonical wheels. So to get back to syntax, what's nice about a "strong clear" syntax like infix math or c-style function declarations is that they make purposes clear and make boundaries clear. The useful of designing a "real language" is doing that. You can do everything with s-Expression but if it just your new language for doing X, you'll putting forward your purpose in a loose, flabby way. If you expression-language isn't going to be just rolled into LISP, it will just have all the weaknesses and of the strengths of LISP.
- Tyr42 13y agoWhy not use postfix notation, and make a stack based language like Forth? Even less parsing to do.
- mathgladiator 13y agoa million times this. Having written programming languages, this is the best advice to give. First, you focus on what makes you language novel, interesting, and special; once you know that have something worth while, you sit down and invent the syntax that makes it pretty and readable.
- ahy1 13y agoSo what if the syntax is (part of) what makes your language novel, interesting and special?
- mathgladiator 13y agoFrom my experience, syntax tends to align with bike shedding. Semantics, on the other hand, tend to be nuclear reactors.
- exDM69 13y agoI'm going to give a differing opinion here, depending on what you write your interpreter and/or compiler with, using s-expressions may not be the best choice. While using s-expressions is obviously the right thing to do if you are writing your compiler in some dialect of Lisp, it may not be the best choice if using another language. In particular, I have past experience from writing several toy programming language interpreter and compiler prototypes in Haskell. Representing the abstract syntax tree with a tree structure and sum types is easy and convenient and writing the actual parser (using e.g. Parsec) is trivial and doing a pretty printer isn't hard either (using Hughes-PJ pretty printers). If you have not tried it, I recommend doing a small programming language prototype in Haskell. It's a very good exercise and really fun.
- joe_the_user 13y agoI 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 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.
- exDM69 13y agoOk, 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 https://github.com/rikusalminen/funfun LLVM compiler for a toy functional programming language (with type inference!) https://github.com/rikusalminen/slolog https://github.com/rikusalminen/slolog Prolog-esque logic programming language