Hi Sean --
This gets asked about just frequently enough that I think people would
greatly value it if you were to provide it, yet not so often that we ever
seem to get around to it ourselves. I.e., we'd love to see this developed
and contributed back.
That said, I feel unclear myself about what the right direction to pursue
is for this case. And, to be perfectly honest, I also find myself second
guessing the current specification and syntax of type selects.
Starting with your proposal:
> union U {
> var x : int;
> var y : string;
> }
> var u : U;
> u.x = 5;
>
> type select u {
> when U.x do writeln("x");
> when U.y do writeln("y");
> }
This feels a little funny to me given the current definition of type
select because I would expect the expressions following the 'when' clauses
to evaluate to type expressions (e.g., 'int' and 'real') rather than the
variables that I think of U.x and U.y to refer to. Also, if we think of
type select as accessing the type of the expression (i.e., u.type) then it
seems like that should evaluate to the union type 'U' itself rather than
one of the field types -- to do otherwise feels non-orthogonal. Both in
the sense of "What if I wanted to query whether the type of u was a union
or an int?" and "type selects should be equivalent to chained conditionals
on 'expr.type'."
Since the time that we originally specified and implemented type selects,
I've been having second thoughts about whether we made the right
decisions. So the big caveat here is that what follows is my personal
opinions and others on the team may disagree. I think we may want to kick
this around on chapel-developers a bit and consider pushing it to
chapel-users to see if we get different viewpoints there -- especially if
we don't reach an easy consensus here.
If I were to keep the 'type select' syntax, I would tend to expect it to
behave as follows. Given:
type t = typeFunction();
var x: typeFunction();
proc typeFunction() type {
if (coinFlipIsHeads()) {
return int;
} else {
return real;
}
I'd want the user to write this:
type select t { // type alias OK
when int do writeln("i");
when real do writeln("r");
otherwise do writeln("?");
}
type select x.type {
when int do writeln("i");
when real do writeln("r");
otherwise do writeln("?");
}
The reason is because it feels healthy to me to either always expect a
type expression or a value/variable expression in this context rather than
permitting both; yet if we were to only support the value/variable case
(the second), it wouldn't permit us to make queries on type aliases like
't'. Seems broken.
But, since that time, I've found myself thinking we should abandon the
'type select' syntax and just extend normal select statements to support
type expressions as well. That is, given that today we can write things
like:
if (t == int) {
} else if (t == real) {
} else {
}
and
if (x.type == int) {
} else if (x.type == real) {
} else {
}
It seems natural to write "type selects" as simply:
select t {
...
}
select x.type {
...
}
I.e., conditionals-on-exprs:selects-on-exprs are analogous to
conditionals-on-types:selects-on-types.
Unions cause problems in this case too, though, because given:
union U {
var x: int;
var y: string;
}
var u: U;
u.x = 5;
there's a question as to whether u.type refers to the union (which seems
most natural) or to the "active" field. That is, if the former is
true, I couldn't write:
select u.type {
when int do
when real do
otherwise
}
but if the latter is true, I wouldnt' be able to distinguish between a
variable that's a union and one that's something else.
And that's where I pause and wonder whether we need some additional
mechanism to talk about the currently active/dynamic type. Another place
where such a concept could be useful would be to query the dynamic (vs.
static) type of a subclass. Maybe the same concept could be used for
both? I.e., I'm imagining something like:
select u.dynType { // not sure I like 'dynType' as the name...
when int do ...
when real do ...
otherwise ...
}
where we might also be able to use this in cases like:
class C { ... }
class D: C { ... }
var myC: C = if (coinFlipIsHeads()) then new C() else new D();
select myC.dynType {
when C do
when D do
}
It's worth noting that the original type select cases I mentioned at the
top of this can be completely resolved statically while these two cases
would require dynamic information and some sort of code manipulation to
map the type expressions to some sort of runtime expression (given that we
don't have dynamic representation of most types).
And now I've gotta run home -- hope this is useful food for thought and
sorry that there's not a clearer path here... I'm interested in what you
think.
-Brad
------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers