"Context" is implemented as type coercion calls, implicitly inserted
by the compiler.
There are five types used in these calls. The "..." below denote
the positions where these contexts typically occur, using common
Perl 5 operations as examples:
Void # ...; 1;
Single[::of] # chdir ...;
Plural[::of] # reverse ...;
RW[Single[::of]] # chop ...;
RW[Plural[::of]] # shift ...;
The compiler is responsible to translate sigils, "is rw" and "is context"
notations into the types above. In the object model, the five types are
represented as roles.
Denotationally, the signature for = and := are as below:
proto infix:<=> (RW[::T]: T) --> RW[T]
proto infix:<:=> (Plural[RW[::T]]: Plural[RW[Any]]) --> Plural[RW[::T]]
Note that both forms only have one invocant; dispatch is decided by the
left-hand side's type.
Each builtin type "does" exactly one of the five types above.
Int does Single[Int]; # 3
Rule does Single[Rule]; # rx{123}
Args does Plural[Any]; # \(1,2,3)
Sigs does Plural[RW[Any]]; # :($x,$y,$z)
Tuple[::T] does Plural[T]; # (1,2,3)
Range[::T] does Plural[T]; # (1..3)
Scalar[::T] does RW[Single[T]]; # $IN
Array[::T] does RW[Plural[T]]; # @ARGS
Hash[::T] does RW[Plural[T]]; # %ENV
List[::T] does RW[Plural[T]]; # ($IN,@ARGS,%ENV)
Note that the list-associative infix:<,> has two variants: If all its arguments
does RW, it returns a List; otherwise it returns a Seq. This matches the Perl5
behaviour:
perl -e '($_, $_) = 3'; # okay
perl -e '($_, 7) = 3'; # error
For user-defined concrete classes without any "does" clauses, we automatically
derive a "does Single[::t]" for it.
During compile time, the local type inferencer looks up coerce:<as> calls for
each expression that does not match its expected type:
proto coerce:<as> (::from, ::to) --> ::to
If the type of ::from is known at compile time, the availability of these
coercion forms are checked at compile time as well, so it's subject to
constant folding. Hence if the programmer wants to make "3 = 4" work, a
corresponding form must be declared at compile time:
multi coerce:<as> (Int, RW[Single[Int]]) {...}
otherwise it raises a compile time error.
Okay, the differences between my "context and coersion" and your "context and coersion" follow:
All contexts are types, and my contexts weren't parameterized. List does Plural.
To create a new context, you derive it from an existing context (and mark it as a context).
Here's the important one: No multiple inheritance is allowed in the context hierarchy. This means that Perl 6's contexts cannot be isomorphic to types. See "What's in a context" in my proposal for a proof. (Short version: if there is MI in the context hierarchy, there is no "want" switch, ever, that is guaranteed unambiguous).
Context has an important and cool relationship to MMD functions, described in the very first section.
The way we solve the (\@array).foo problem is quite simple: Every rvalue mention of a variable (including arrays) is a .fetch call on the container; the fetch is polymorphic in context. \$foo (and \@foo) just return the container itself. \42 creates an anonymous scalar, as does \\$foo === \(\$foo).
We'll argue about the parameterization on IRC.
Posted by: Luke Palmer | 2006.01.04 at 02:42 PM