Open asoffer opened 2 years ago
It dawn's on me that we already support this when blocks have no arguments (this is how else-if chains work) so the extension is pretty feasible, even without the >> operator.
If file.With returned a monad error eg optional
The second scope should be able to forward with >> to a third nested scope
Could you provide a sample of what this would look like? I'm having trouble understanding.
file.With ("input.txt") open >> monad.unpack >> file.Lines () each >> parse_command ()
forward [n: i64] { horizontal += n }
down [n: i64] { vertical += n }
up [n: i64] { vertical -= n }
where you define Monad.unpack
to short-circuit (e.g. like if false
) if the optional is None
This is (afaict) the?
from Rust, except it maybe doesn't RETURN_IF (more like BREAK_IF)
I see. Yes, you could do this, having the monad scope try to unwrap and enter the body if it succeeds and pass over if it fails. However, the file.With scope could do the same. In fact it already does if you don't provide an error handling scope. The question is, what do you do if you really do want a scope for error handling?
Let me try again to understand the error issue. We're going from this:
file.With (filename) open [f: file.File] {
file.Lines (f) each [line: []char] {
ProcessLine(line)
}
} onError {
// do something
}
to something like this
file.With (filename) open >> file.Lines () each [line: []char] {
ProcessLine(line)
} // where does onError go? This is the close curly brace of file.Lines
Let's remove some sugar, though.
file.With (filename) open >> {
file.Lines () each [line: []char] {
ProcessLine(line)
}
} onError { ... }
That seems ok. We can even compress it back to 3 lines if we want
file.With (filename) open >> { file.Lines () each [line: []char] {
ProcessLine(line)
} } onError { ... }
How do I feel about this? Effective Icarus now warns you about onError scope placement when using syntax sugar, but other than that ... fine? The real issue is that we probably want something about our onError to redundantly confirm which scope it's holding errors for. And if you do that, you don't need the extra curly braces. And if you don't do that, you've made a bit of a confusing construct.
All this said, I'm generally in favor of the >>
syntax. I think you have lots of options for what this syntax looks like (within the confines of the language), so it doesn't have to be >>
. But if that character is free it makes some amount of sense.
There seems to be a somewhat common pattern with nesting scopes, for which I think the following example is illustrative:
We've specified
f
but only use it to pass to the next scope. It would be nice if we could compose these scopes directly.This proposal is for a non-overloadable operator (tentatively spelled
>>
) which can connect nested scopes, passing the arguments provided from the outer block directly as arguments to the inner scope. Rewritten, the above code would be:There are a few caveats here:
Lines
andeach
to resolve parsing ambiguities. It also would allow us to feed further arguments ifLines
had accepted any. So more carefully, the arguments provided from theopen
block are passed as a prefix of the arguments toLines
, and more can be placed in the parentheses.file.With
error scope anymore. We could place it beforeopen
, meaning this mechanism only works for the last block in the scope. This solution feel satisfying to me though.It's worth mentioning what my Advent Of Code day 2 solution would look like. If we adopted this, and changed the parsing rules slightly to be smarter about newlines (I think this is possible, but I'm not 100% positive), the solution would look like:
Which I think is particularly elegant.