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

Reply via email to