-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Where clauses are wonderful but come with a few goofy bothers.
- Causes reindentation. Either the where token is put at the end of the main expression, which then causes the line to not be reorder-able, or the where token is given its own line and all the definitions have to be either double indented or plain ugly and hard to distinguish from the where token itself.
- Reverses order. Sometimes it is nice to have a few unimportant definitions after the main body, but just as often it'd read better to have the values incrementally built in each successive line. Where clauses also muddle with that as I can never decide whether to incrementally build up, towards the main expression, or down, as is more natural.
I'm thinking of the following syntax.
roots = { a, b, c }.
determinant = b * b - 4 * a * c
oneSide = plusOrMinus. (-b `plusOrMinus` sqrt determinant) / (2 * a)
compare determinant 0 | match
LT. None
_. Some $ (oneSide (-), oneSide (+))
The parsing here gets somewhat complicated. Some preprocessor sees the newline in the continuation of this expression and goes to check if there's an = in the line (it can abort early if it comes across multiple non-whitespace tokens, the benefits of not having powerful declarations!). If there is, then the rest of the captured tokens (the offsides rule and parentheses are the only way to capture, there is no notion of the natural end of an expression -- the parser will try to turn the entirety of the captured tokens into an expression) will be fed through the offsides rule. Using brackets to show captured tokens:
[roots = { a, b, c }.
[determinant = b * b - 4 * a * c]
[oneSide = plusOrMinus. (-b `plusOrMinus` sqrt determinant) / (2 * a)]
[compare determinant 0 | match
LT. None
_. Some $ (oneSide (-), oneSide (+))]]
If every block is a definition, the last block will be taken as the value of the expression. If there is more than one, the others/following expressions will be flagged as dead code and possibly fail the parse.
Definitions can be prepended with ex and the expression will instead evaluate to a record with the binding name and expression becoming a row. Blocks that are not definitions will be flagged as errors.
roots = { a, b, c }.
ex determinant = b * b - 4 * a * c