# Lyn Old swedish for maple. ## Scheme is cool ...but has too many parentheses. ## TCL is cool (yes, it really is) ...but littering `$` all over the place is annoying. ## Can we build something in-between? Maybe. `lyn` is effectively a pre-processor for GNU Guile, adopting TCL's 'everything is a command' attitude while keeping Scheme semantics. Let's start with an example, `examples/guile.lyn`: ``` define-syntax-rule (for init condition post body) { expand init do () ((not (expand condition))) { expand body expand post } } define (sum n) { define s 0 for (define i 0) (< i n) (set! i (1+ i)) { set! s (+ s i) } get s } display (sum 1000000) newline ``` If you're familiar with Scheme, this should look eerily familiar. Effectively, a command starts with a thing to apply, follows with some arguments and ends with a newline or `;`. `()` applies a command to be used as an argument, and `{}` specifies a list of commands. The top-level can also be thought of as a block of commands. When encountering a `{`, a matching `}` must be found before the command can be finished. `{}` can itself contain newlines just fine. A command can also be continued over multiple lines by using `\`, as in `examples/multiline.lyn`: ``` if (< 10 20) \ {display "math works"; newline} \ {display "what"; newline} ``` There are two 'builtins' beyond what GNU Guile provides (all GNU Guile functions can be called as commands), namely `get` and `expand`. They're effectively the identity commands, i.e. `get` returns the value that was passed into it, and `expand` expands a macro as if `expand` weren't there. These are useful because, again, *literally* everythin is a command, so if you want to return a value you can't just write `arg` as the last element of a `(begin ...)` or whatever, because that value will be interpreted as a command. Same thing with macros. Note that `values` is effectively the same thing as `get`, but I think `get` has a nicer symmetry with `let`/`set`. `macroexpand` is (maybe somewhat surprisingly) not equivalent to `expand`, as `macroexpand` can't handle `(define ...)`. Since `;` ends commands, `#` is used for comments instead. The current implementation just outputs all code into `/tmp/output.scm`. Terrible, I know, but good enough to start playing around with it. Have a look at that file to see just how closely this syntax matches Scheme, while (IMO) being easier to read. In particular I find this style to be easier to write, as I sometimes find that I have to count how many parentheses deep some expression is. I'm aware that there are tools that help with this, but I tend to want to have as little between me and my code. ## Drawbacks + Code generation is arguably not as trivial as with S-expressions. Ideally traditional Scheme functions could be interleaved with this syntax, though I haven't really looked into this option. + Certain coding styles (like placing `{` on a new line) are more clumsy to use + The current implementation parses `()` with multiple commands but produces incorrect Scheme. I'm not sure whether to fix the outputting or disallow multiple commands within `()` (that's what `{}` is for) ## Isn't this all a bit silly? Yes. Schemers are presumably used to the parentheses and would prefer them over this, while the TCL crowd likely don't like the shift away from user interfaces. I don't expect anyone to really have any interest in this thing, but if I'd get to choose I would probably want to use a scripting language like this over any other current alternatives, of which there are many excellent ones. ## Building and running `make`, after which `./lyn examples/guile.scm` for example. REPL not supported at the moment, though it probably could be added.