links
links copied to clipboard
Braces are suspenders
Sam and I have discussed several times that we would like to interpret the expression { M }
as fun() { M }
, since it is useful syntactic sugar for effectful programming in a call-by-value setting. As it stands right now that is not possible because the expression { M }
is interpreted as a block, i.e. a local scope for the evaluation of expression M
. For example, today one can write
links> var x = { println("hello"); 40 };
hello
x = 40 : Int
links> x + 2;
42 : Int
Here x
gets bound to 40
after the string "hello"
has been printed. This usage of block expressions do not appear to be widely used (if used at all) in our examples. Thus we can probably dispense of block expressions of this kind without much fuss.
A slightly more useful usage of block expressions happens primarily in handler code:
links> var x = handle({println("hello"); do Ask}) { case Ask(resume) -> 40 };
hello
x = 40 : Int
links> x + 2;
42 : Int
Here the braces are used to turn the sequence println("hello"); do Ask
into a single block expression (the same trick can be used for switch
rather than handle
). We can possibly eliminate the need for braces here by generalising the grammar for handle
, switch
, etc.
Implementing the suggested changes paves the way for interpreting { M }
as a thunked expression. Obviously, this would be a breaking change, however, I doubt it will affect any live Links code outside of the examples/handlers
directory.
I forgot to remark that some tests under tests/
make use of { M }
.
I reckon it may be possible to implement this change under a flag initially by slightly modifying the block
production in the rule postfix_expression
along the lines of
postfix_expression:
...
| block { if braces_are_suspenders then Thunk (remove_block_tag $1) else $1 }
...
At the risk of falling prey to Wadler's Law, this seems like it would be an incredibly confusing design, since in C/Java/JS family languages unaccompanied braces are almost always just block delimiters. Whatever one thinks of this convention it seems unwise to depart from.
What about the alternative of
lazy {block} --> fun () {block}
force(e) --> e()
? Why not something like this (possibly with more compact syntax (e.g. {{block}} )?