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

Reply via email to