What i was proposing is for switch to cram "not match" and the index of the 
matching case into one int because using -1 seems natural and it will work well 
with the tableswitch.

There’s two levels here, and I think part of the confusion with regard to 
pattern translation is we’re talking at different levels.

The first level is: I’ve written a deconstructor for class Foo, and I want to 
match it with instanceof, case, whatever.  I need a way to “invoke” the pattern 
and let it conditionally “return” multiple values.  Carrier is a good tool for 
this job.

The second level is: I want to use indy to choose which branch of a switch to 
take, *and* at the same time, carry all the values needed to that branch.  
Carrier could be applied to this as well.

Somewhere in between, there’s the question of how we roll up the values in a 
compound pattern (e.g., Circle(Point(var x, var y) p, var r) c).  This could 
involve flattening all the bindings (x, y, p, r, c) into a fresh carrier, or it 
could involve a “carrier of carriers”.  There are many degrees of freedom in 
the translation story.

What Jim is proposing here is a runtime for bootstraps to make decomposable 
tuples that can be pass across boundaries that agree on a contract.  This could 
be a simple return-to-caller, or it could rely on sharing the carrier in the 
heap between entities that have a shared static typing proof.

To come back to the carrier API, does it means that the carrier class is always 
a nullable value type or does it mean that we need to knob to select between a 
primitive type or a value type ?

Probably the carrier can always be a *primitive* class type, and the null can 
be handled separately by boxing from QCarrier$33 to LCarrier$33.  All the 
Carrier API does is provide a constructor which takes N values and returns a 
carrier; at that point, you already know you want a non-null value.  Consumers 
higher up the food chain can opt into nullity.


Reply via email to