Missing features in pattern failure
accum [].asMap() for [k, v] in foo { _.with(k, v) }
This code does not do the right thing if one of the elements of foo is
not a pair: it will skip it rather than failing. Currently this has to
be rewritten using an explicit def:
accum [].asMap() for temp ? (def [k, v] := temp; true) in foo
{ _.with(f(k), f(v)) }
or
accum [].asMap() for temp in foo { _.with(def [k, v] := temp; f(k),
f(v)) }
but both of these are ugly.
What I would like for this is something like Haskell's "irrefutable
patterns", which turn match failure in a subpattern into a program
failure.
This comes to mind:
accum [].asMap() for via (irrefutable) [k, v] in foo { _.with(f(k),
f(v)) }
but with the current protocol for a via-function, it can't control
what ejector is supplied to a subpattern.
This inability has another effect:
----------------------------------------------------------------------
Since nothing in in a Kernel-E pattern does or can substitute the
ejector, once a match of some pattern against some value has failed,
it is impossible to reconstruct which part of the value did not match.
If the ejectors for subpatterns were nested (much as happens in the
interaction between TextWriters and printed objects) then we could
construct a chain of nested exceptions as we unwind in the pattern
which documents where the failure was.
Example:
def [==1, [==2, [==3, ==4]]] := [1, [2, [9, 4]]]
would generate the exception
makeTupleFailure(1,
makeTupleFailure(1,
makeTupleFailure(0,
makeSamePattFailure(9, 3)))
When each ListPattern executes its subpatterns, it provides an ejector
which calls the outer ejector:
to matchBind(specimen, ejector, env) {
for index => subpattern in myPatterns {
subpattern.matchBind(specimen, fn subfailure {
ejector(makeTupleFailure(index, subfailure))
}, env)
}
}
Similarly, ViaPattern would need to be changed such that the via-
function can specify the ejector the subpattern gets, as well as the
specimen.
(ListPattern and ViaPattern are the only non-atomic patterns remaining
in Kernel-E.)
I think this might enable some interesting uses, but I don't have any
concrete examples besides "nice error messages". They would be very
nice error messages, though.
On the other hand, it's a lot of objects to be allocated. But a lot of
uses of 'via' generate closures each time anyway; perhaps the answer
is "just" work on optimizing them out (don't make reified nested
ejectors if you can compile the patterns; don't make exceptions if
nothing is looking).
--
--
Kevin Reid <http://homepage.mac.com/kpreid/>