On Tue, May 03, 2005 at 09:53:59PM +0800, Autrijus Tang wrote:
: On Tue, May 03, 2005 at 05:32:44AM -0700, Larry Wall wrote:
: > :     # Type Instantiation?
: > :     sub apply (&fun<::a> returns ::b, ::a $arg) returns ::b {
: > :   &fun($arg);
: > :     }
: > 
: > The first parameter would be &fun:(::a) these days, but yes.
: > (Stylistically, I'd leave the & off the call.)
: 
: So, the "returns" trait is not part of a function's long name, but
: it can still be matched against (and instantiated)?

Well, we've made some rumblings about the return type being a
tiebreaker on MMD after all other invocants have been considered,
but other than that, I don't consider it a part of the long name,
at least for standard Perl 6 as currently defined.  An MLish version
of Perl might.  But maybe installing the return type inside the
signature is a way to indicate that you want the return type considered.

: Hrm, is it specific to the "returns" trait, or we can match against 
: any traits at all?
: 
:     sub foo ($thingy does Pet[::food]) { ... }

Which is basically what

    sub foo (Pet[::food] $thingy) { ... }

is doing already, unless you consider that what $thingy returns is
different from what it actually is, which would be odd.

: Also, S12 talks about "is context":
: 
:     method wag ([EMAIL PROTECTED] is context(Lazy)) { $:tail.wag([EMAIL 
PROTECTED]) }

That is probably misspecified slightly, insofar as the context is
already lazy by default.  The problem is that the incoming Lazy
is being bound as the .specs of an Array, and I was thinking the
flattening aspects of an array might cause a double flattening
when we pass it on to the delegated method.  But I suppose if we
work it right, a simple

    method wag ([EMAIL PROTECTED]) { $:tail.wag([EMAIL PROTECTED]) }

should coalesce the two abstract flattenings of the two calls into one
actual lazy flattening.

: What is the type of "Lazy" here?

Intended to be an ordinary lazy list such as you always get in for
the list unless you force it to be eager.  It basically is what is
bound to the .specs of the Array for its generators, if I'm thinking
about it right.

: Also, is "context" a role or a class?

I'd call it a trait in this case since it's apparently doing heavy duty
context magic to the parse (which you can't do with a method anyway...)

: If it is a class, how does it parameterize over "Lazy" ?

It's mostly there to allow "is context(Scalar)" so we can have
a subroutine call with a list of scalars.  But we also want "is
context(Eager)" functionality to force eager flattening of the list.
The latter currently has a shorthand of

    sub foo ([EMAIL PROTECTED]) {...}

to get a P5 style immediate flattening.

: > :     # Single colon as tuple composer?
: > :     my $Triple            ::= :(Bool, Int, Str);
: > :     my $TripleTuple       ::= :($Triple, $Triple);
: > :     my &pair_with_int     ::= -> Type ::t { :(::t, Int) };
: > 
: > I think of it as the signature composer.  Does Haskell call them
: > tuples?  That word tends to mean any immutable list in other circles,
: > though I suppose :(4, 2, "foo") could be construed as a type whose
: > values are constrained to single values.
: 
: Err, sorry, I meant "tuple type composer".  In haskell:
: 
:     -- Value --           -- Type --
:     (True, 1, "Hello") :: (Bool, Int, Str)
: 
: This was because I couldn't think of other operators other than ","
: to operate on types inside :().  Come to think of it, there are lots
: of other things possible:
: 
:     my $SomeType ::= :((rand > 0.5) ?? Bool :: Int);

I don't think that amount of generality should be allowed in :(), at least,
not without something explicitly interpolative, like

    my $SomeType ::= :( ::( (rand > 0.5) ?? Bool :: Int ) );

: Also, is it correct that (4, 2) can be typed as both a :(Eager) list and a
: :(Any, Any) tuple?  Is it generally the case that we can freely typecast
: unbounded list of values from (and to) bounded ones?

I don't offhand know what restrictions we might want to put on it.

: > But it makes :(int $x) terribly ambiguous if it's an evaluative
: > context.  (Which is why we wanted :() in the first place, to avoid
: > such evaluation.)
: 
: Evaluative context?
: 
: However, I'm a bit confused now.  Does a :(...) expression stand for a
: type, a variable binding, or both?
: 
:     :($x)     # variable binding or deref $x into a type?
:     :(Int)    # a type?
:     :(Int $x) # bind a type into $x?

I was thinking of it only as signature syntax, so it would always be
a variable binding, or pseudo-binding where it doesn't make sense to
actually create a variable.  I was thinking that the syntax might even
just allow you to drop the identifier, so :($:?%,*@) is a valid type,
identical to :($x: ?%y, [EMAIL PROTECTED]) when the names don't matter.

By the way, the problem with just throwing a "returns" in the sig is
that

    :($x: ?%y, [EMAIL PROTECTED] returns Int)

would be taken as

    :($x: ?%y, Int [EMAIL PROTECTED])

So maybe it would have to be written

    :($x: ?%y, [EMAIL PROTECTED], :returns(Int))

or maybe something like

    :($x: ?%y, [EMAIL PROTECTED] --> Int)
    :($x: ?%y, [EMAIL PROTECTED] ==> Int)
    :($x: ?%y, [EMAIL PROTECTED] >> Int)
    :($x: ?%y, [EMAIL PROTECTED] » Int)

which suggests we could have return types on pointy subs:

    $result = do given foo() -> $x --> Int { $x // $default }
    $result = do given foo() -> $x ==> Int { $x // $default }
    $result = do given foo() -> $x >> Int { $x // $default }
    $result = do given foo() -> $x » Int { $x // $default }

and expect $result to contain the integer value of either $x or $default.
But we can solve that another day.

: If all three are allowed, then :($x) itself is ambiguous...  What would
: these mean, then?
: 
:     :(:(Int $x) | :(Str $y));
:     :((Int $x) | (Str $y));

I expect we can probably disallow or ignore the use of variable names
where nonsensical.

Larry

Reply via email to