On Thu, Jun 30, 2005 at 09:25:10AM +0800, Autrijus Tang wrote: : Currently, does this: : : sub foo (::T $x, ::T $y) { } : : and this: : : sub foo (T $x, T $y) { } : : Means the same thing, namely : : a) if the package T is defined in scope, use that as the : type constraint for $x and $y : : b) otherwise, set ::T to be the most immediate common supertype : of $x and $y. : : Is this understanding correct? I'd like to disambiguate the two cases : by making ::T in parameter list to always mean type variable (sense b), : and the bare T always mean type name (sense a)?
I think it would be good to distinguish those, but I've been mulling over whether ::T should be the syntax for b. (And also whether b is the "correct" way to think about it in Perl 6.) The problem with using ::T for "autovivify your type from the argument" is that ::($x) doesn't mean that, and it looks like it should. The :: does imply indirection of some sort in either case, but it's two very different kinds of indirection. ::($x) can't declare a lexical alias for some type, whereas ::T presumably could, though your formulation seems more of a unificational approach that would require ::T everywhere. In other words, if we do type binding like b, we would probably want to generalize it to other binding (and assigning?) contexts to represent the type of the bound or assigned object, and at the same time create a lexical alias for the bare type. So we might want to be able to say ::T $x := $obj; my T $y = $x; and mean something like (my type T) $x := $obj my T $y = $x; In that formulation, the unificational approach looks more asymmetrical: sub foo (::T $x, T $y) { } meaning sub foo ((my type T) $x, T $y) { } On the other hand, if we continue the trend that multiple my's in the same scope declare the same variable (possibly with warning), then sub foo (::T $x, ::T $y) { } would presumably be okay semantically, even if the second ::T is construed as warning bait. But it also goes against the grain to autolexicalize something based on the sigil, so we probably should consider ::T a variable and require the sigil everywhere in the absence of a more explicit declaration. ...Except for the inconvenient fact that it would conflict with the use of ::T as a literal-but-not-yet-declared type, which is valid even in signatures, and the b form abrogates that interpretation. So either we need a different sigil for type variables, or a syntax for explitly binding and declaring an autovivified type. (Which, interestingly, could also be used in rvalue context.) So maybe we really want something like sub foo ((my T) $x, T $y) { } for the asymmetrical case, and sub foo ((my T) $x, (my T) $y) { } for the type unificational case. Maybe we can shorten that to sub foo ((T) $x, (T) $y) { } within an existing "my" context, such as parameter lists. And maybe that's even how we suppress the warning for duplicate "my T" declaration. For bare assignment with run-time type capture, you'd have to say my $x; (my T) $x = $obj; but we also don't have to dup the "my" when there already is one: my (T) $x = $obj; my (T) $x := $obj; In either case, the actual type is bound rather than assigned, but I don't think that makes any effective difference since types are always represented by object refs... =begin hole-poking mode Larry