On 09/16/2012 06:32 PM, David A. Wheeler wrote: > Per Bothner: >> You might find this interesting: >> http://per.bothner.com/blog/2010/Q2-extensible-syntax/ > > Thanks for the pointer! > > This has somewhat similar goals to the "readable" project, though with a different approach. The big difference is that I decided it was important to have a generic notation for *any* s-expression. Why? And what does that mean? I guess it might be neat to have an alternate notation that maps bi-directionally to S-expressions, but that seems like a needless constraint if you're trying to design a more user-friendly language. I think the better goal is a language that is *compatible* with Scheme, in that you can seamlessly call between the languages, including compatible data types. E.g. in an R7RS world you should be able to import an Infix-Scheme library into a Scheme library and vice versa. > It's probably fairest to compare Q2 to the "sweet-expression" notation: > * Sweet-expressions have infix, though not precedence. Actually, precedence *could* be added, as discussed in SRFI-105... I just don't think it's worth it. Well, if you want to support the infix expressions people are used to, need to at least support multiple operators: 3 + 4 + 5 + 6 And of couple people are used to parenthesis as grouping. If you're not going to support those, what is the point? Yes, curly-notation looks more readable than Lisp-notation to someone not familiar with the latter, but it's still going to be bit of a learning curve to write programs in that notation, and it's still going to require a learning hurdle. Also, precedence is handy in some cases. For example assignment: x := x + 1 I agree it's not essential, but I think allowing multiple operators is. > * Both have "juxtaposition for function application" > * Q2 has "Naming a zero-argument function applies it" but this is awkward, indeed, "The exact rule for a distinguishing between a variable reference and a zero-argument function application isn't decided yet." In sweet-expressions, a zero-argument function name is called by adding () after it or around it, e.g., pi(). One rationale for "naming a zero-argument function applies it" is command-line/shells - REPLs and simple scripts. Considering typing a command to a Unix shell. People expect if you type a command with no arguments that it is applied with no arguments. That part at least seems natural and expected. Using () as a magical suffix to indicate application - but *only* for the zero-argument case - is IMO ugly. I'd rather come up with a semantics so I don't have to do that. One idea I've considered is to distinguish commands from functions. A command is lexically bound, rather like a macro, but with normal evaluation. Commands (and macros and builtins) may have have variable arities, keyword arguments, and so on. They do not have run-time representation. In contrast, a function is a value. It is created with a lambda expression, and used with an explicit apply command. This of course takes us further from Scheme/Lisp, but may be worth considering. It is worth noting that pure functional languages (like Haskell) don't have this problem, because a zero-argument function is the same as a lazily-evaluated variable. In an impure-functional language like Scheme that if you seldom pass a zero-argument function as a value; usually you apply it. So that should happen you if mention it, without requiring awkward syntax, at least if you have a language with "juxtaposition for function application". The rare case where you need to pass a a zero-argument function un-applied is rare, and easily be worked around, for example with a dummy argument. > * "Flexible token format" - both require operators to be delimited. > * "Use indentation for grouping" - both use indentation for grouping > * "Block expressions yield multiple values" - In sweet-expressions, you use usual Scheme procedures, including value, instead of having special syntax. I'm not 100% sure the multiple-values semantics for blocks (along with append-values semantics for statement separation) is a good thing, but it does compose well and has some other nice properties. > * REPL: In sweet-expressions, you usually end a line with ENTER ENTER. Q2 doesn't, but I worry that you have to be careful or it'll end where it syntactically might not need to. I think there are two primary uses of a REPL: (1) Running pre-existing commands with appropriate arguments. (Think: command shell.) (2) Trying out expression and commands to see how they work, to explore, and/or to learn a language or feature. In both cases, having to end each expression with ENTER ENTER seems unfriendly. The Q2 convention is simple and works pretty well. It's not going to always work correctly if you feed a "program" to the REPL line-by-line, but I don't see that is a priority. -- --Per Bothner xxxxxx@bothner.com http://per.bothner.com/