This file was automatically generated from http://svn.pugscode.org/pugs/docs/notes/context_coercion_parameterized_types.pod on Wed Jun 6 22:16:47 2007 GMT, revision 16639.
Context and Coercion - The interplay of the method call and the call chain
(This is Audrey's proposal that implements a similar system to
context_coercion_traits.pod, but use normal parameterized types instead
of a special trait to encode contexts.)
"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 Tuple. 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.