Contexts and contextualizers
What are contexts and how to get into them
A context is needed, in many occasions, to interpret the value of a container. In Perl 6, we will use context to coerce the value of a container into some type or class, or decide what to do with it, as in the case of the sink context.
Sink is equivalent to
void context, that is, a context in which we throw (down the sink, as it were) the result of an operation or the return value from a block. In general, this context will be invoked in warnings and errors when a statement does not know what to do with that value.
my = -> ;; # OUTPUT: «WARNINGS:␤Useless use of $sub in sink context (line 1)␤»
In general, blocks will warn if evaluated in sink context; however, gather/take blocks are explicitly evaluated in sink context, with values returned explicitly using
In sink context, an object will call its
sink method if present:
sub foofoo# OUTPUT: sink called
This context, and probably all of them except sink above, are conversion or interpretation contexts in the sense that they take an untyped or typed variable and duck-type it to whatever is needed to perform the operation. In some cases that will imply a conversion (from Str to Numeric, for instance); in other cases simply an interpretation (IntStr will be interpreted as Int or as Str).
Number context is called whenever we need to apply a numerical operation on a variable.
my ="1 ";my ="3 ";say +; # OUTPUT: «4␤»
In the code above, strings will be interpreted in numeric context as long as there are only a few digits and no other characters. It can have any number of leading or trailing whitespace, however.
Numeric context can be forced by using arithmetic operators such as
-. In that context, the
Numeric method will be called if available and the value returned used as the numeric value of the object.
my = True;my = False;say +; # OUTPUT: «1␤»say .Numeric; # OUTPUT: «1␤»say .Numeric; # OUTPUT: «0␤»my = <a b c>;say True+; # OUTPUT: «4␤»
In the case of listy things, the numeric value will be in general equivalent to
.elems; in some cases, like Thread it will return an unique thread identifier.
In a string context, values can be manipulated as strings. This context is used, for instance, for coercing non-string values so that they can be printed to standard output.
put ; # OUTPUT: something meaningful
Or when smartmatching to a regular expression:
put 333444777 ~~ /(3+)/; # OUTPUT: «｢333｣␤ 0 => ｢333｣␤»
In general, the
Str routine will be called on a variable to contextualize it; since this method is inherited from Mu, it is always present, but it is not always guaranteed to work. In some core classes it will issue a warning.
~ is the (unary) string contextualizer. As an operator, it concatenates strings, but as a prefix operator it becomes the string context operator.
my = [ [1,2,3], [4,5,6]];say ~; # OUTPUT: «1 2 3 4 5 6␤»
This will happen also in a reduction context, when
[~] is applied to a list
say [~] [ 3, 5+6i, Set(<a b c>), [1,2,3] ]; # OUTPUT: «35+6ic a b1 2 3␤»
In that sense, empty lists or other containers will stringify to an empty string:
say [~]  ; # OUTPUT: «␤»
~ acts also as buffer concatenation operator, it will have to check that every element is not empty, since a single empty buffer in string context will behave as a string, thus yielding an error.
say [~] Buf.new(0x3,0x33), Buf.new(0x2,0x22);# OUTPUT: «Buf:0x<03 33 02 22>␤»
my = Buf.new(0x3, 0x33);my = ;my = Buf.new(0x2,0x22);say [~] , , ;# OUTPUT: «Cannot use a Buf as a string, but you called the Stringy method on it
~ is putting in string context the second element of this list,
~ is going to be using the second form that applies to strings, thus yielding the shown error. Simply making sure that everything you concatenate is a buffer will avoid this problem.
my = Buf.new(0x3, 0x33);my = Buf.new();my = Buf.new(0x2,0x22);say [~] , , ; # OUTPUT: «Buf:0x<03 33 02 22>␤»
In general, a context will coerce a variable to a particular type by calling the contextualizer; in the case of mixins, if the context class is mixed in, it will behave in that way.
my = 1i but 'Unity in complex plane';put ; # OUTPUT: «Unity in complex plane␤»
but creates a mixin, which endows the complex number with a
put contextualizes it into a string, that is, it calls
Str, the string contextualizer, with the result shown above.