=begin pod :kind("Language") :subkind("Language") :category("fundamental")

=TITLE Contexts and contextualizers

=SUBTITLE What are contexts and how to switch into them

A context is needed, in many occasions, to interpret the value of a container.
In Raku, we will use context to coerce the value of a container into some type
or class, or in general decide what to do with it, as in the case of the sink
context. In general, recognizing an object that is in a certain context will
force an implicit coercion by calling a specific method on it.

=head1 Sink X<|sink context>

The I<sink> context is equivalent to what in other languages is called C<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.

=begin code
my $sub = -> $a { return $a² };
$sub; # OUTPUT: «WARNINGS:␤Useless use of $sub in sink context (line 1)␤»
=end code

X<|sinking>
You can force that sink context on L<Iterator|/type/Iterator>s, by
using the L<C<sink-all>|/routine/sink-all> method. L<Proc|/type/Proc>s can also
be L<sunk via the C<sink> method|/type/Proc#method_sink>, forcing them to raise
an exception and not returning anything.

In general, blocks will warn if evaluated in sink context; however,
L<gather/take blocks|/language/control#gather/take> are explicitly
evaluated in sink context, with values returned explicitly using C<take>:

=for code
my @results = gather for 1..1 { ^10 .map: *.take };
say @results; # OUTPUT: «[0 1 2 3 4 5 6 7 8 9]␤»

In this example, C<for> is run in sunk context, and within it, C<map> is too.
 Results are taken explicitly from the loop via gather/take.

In sink context, an object will call its C<sink> method if present:

=begin code
sub foo {
    return [<a b c>] does role {
        method sink { say "sink called" }
    }
}
foo; # OUTPUT: «sink called␤»
=end code


=head1 Number X<|number context>

This context, and probably all other contexts except I<sink> above, are
I<conversion> or I<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 L<Str|/type/Str> to
L<Numeric|/type/Numeric>, for instance); in other cases simply an interpretation
(L<IntStr|/type/IntStr> will be interpreted as L<Int|/type/Int> or as
L<Str|/type/Str>).

I<Number context> is called whenever we need to apply a numerical operation on a
variable.

=begin code
my $stringone = "1                 ";
my $stringthree = "3                        ";
say $stringone + $stringthree; # OUTPUT: «4␤»
=end code

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 C<+> or
C<->. In that context, the L<C<Numeric>|/routine/Numeric> method will be called
if available and the value returned used as the numeric value of the object.

=begin code
my $t = True;
my $f = False;
say $t + $f;      # OUTPUT: «1␤»
say $t.Numeric;   # OUTPUT: «1␤»
say $f.Numeric;   # OUTPUT: «0␤»
my $list= <a b c>;
say True + $list; # OUTPUT: «4␤»
say +"  \n ";     # OUTPUT: «0␤»
=end code

Whitespace in any quantity will be converted to 0, as is shown in the last
statement. In the case of I<listy> things, the numeric value will be in general
equivalent to C<.elems>; in some cases, like
L<Thread|/routine/Numeric#(Thread)_method_Numeric>, it will return an unique
thread identifier.

=head1 String X<|string context>

In a I<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.

=for code :preamble<my $very-complicated-and-hairy-object>
put $very-complicated-and-hairy-object; # OUTPUT: something meaningful

Or when smartmatching to a regular expression:

    put 333444777 ~~ /(3+)/; # OUTPUT: «333␤»

In general, the L<C<Str> routine|/routine/Str> will be called on a variable to
contextualize it; since this method is inherited from L<Mu|/type/Mu>, it is
always present, but it is not always guaranteed to work. In some core classes it
will issue a warning.

L<C<~>|/routine/~> is the (unary) string contextualizer. As an operator, it
concatenates strings, but as a prefix operator it becomes the string context
operator.

=begin code
my @array = [ [1,2,3], [4,5,6]];
say ~@array; # OUTPUT: «1 2 3 4 5 6␤»
=end code

This will happen also in a
L<I<reduction>|/language/operators#Reduction_operators>
context, when C<[~]> 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: «␤»

Since
L<C<~> acts also as buffer concatenation operator|/routine/~#(Operators)_infix_~>,
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>␤»

However,

=begin code
my $non-empty = Buf.new(0x3, 0x33);
my $empty = [];
my $non-empty-also = Buf.new(0x2,0x22);
say [~] $non-empty, $empty, $non-empty-also;
# OUTPUT: «Cannot use a Buf as a string, but you called the Stringy method on it
=end code

Since C<~> is putting in string context the second element of this list,
L<C<~>|/routine/~#(Operators)_infix_~> 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.

=for code
my $non-empty = Buf.new(0x3, 0x33);
my $empty = Buf.new();
my $non-empty-also = Buf.new(0x2,0x22);
say [~] $non-empty, $empty, $non-empty-also; # 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 $described-number = 1i but 'Unity in complex plane';
    put $described-number; # OUTPUT: «Unity in complex plane␤»

C<but> creates a mixin, which endows the complex number with a C<Str> method.
C<put> contextualizes it into a string, that is, it calls C<Str>, the string
contextualizer, with the result shown above.

=head1 Boolean X<|Boolean context>

This context will force a variable to be interpreted as C<True> or C<False>.

    say "Hey" if 7;  # OUTPUT: «Hey␤»
    say "Ahoy" if "";

This context appears in expressions such as C<if> or C<while>, and is
equivalent to calling C<so> on these values.

=for code
say "Hey" if 7.so;          # OUTPUT: «Hey␤»
say "Ahoy" if not set().so; # OUTPUT: «Ahoy␤»

In general, non-zero, non-empty will be converted to C<True>; zero or empty
will be equivalent to C<False>. But C<.so> can be defined to return any Boolean
value we want, so this is just a rule of thumb.

The L«C<?>|/language/operators#prefix_?» Boolean context operator
and the L«C<!>|/language/operators#prefix_!» negated Boolean context
operator will force the Boolean context on an object.

=for code
say ? 0i;    # OUTPUT: «False␤»
say ! :true; # OUTPUT: «False␤»

=head1 List X<|list context>

There are actually several different
L<list contexts|/language/list#List_contexts>, which are better explained in
that page. In general, the list contextualizer is the comma C<,>

    say (3,).^name; # OUTPUT: «List␤»

and the method called in that case is also C<.list>

=for code
Any.list.^name;   # OUTPUT: «List␤»
say 3.list.^name; # OUTPUT: «List␤»
say (^3).list;    # OUTPUT: «(0 1 2)␤»

=head1 Item context

Item or scalar context will deal with complex pieces of data as if they were
a single item. It is forced when you try to assign to a scalar variable

=for code
my $scalar-context = <1 2 3>;
say "→ $_" for $scalar-context; # OUTPUT: «→ 1 2 3␤»

It can be induced using the C<$> operator, that acts as the contextualizer
operator by calling C<item> as a method or routine

=for code
.say for $(1,2,3);      # OUTPUT: «(1 2 3)␤»
.say for (1,2,3).item;  # OUTPUT: «(1 2 3)␤»
.say for item( 1..3 );  # OUTPUT: «1..3␤»

Itemization affects only their behavior in list context; however, they will
still keep their C<Positional> role or other roles they might have:

=for code
$(1,2,3).elems.say;          # OUTPUT: «3␤»
say (1,2,3).item[2];         # OUTPUT: «3␤»
say $( key => 'value')<key>; # OUTPUT: «value␤»

Itemization I<containerizes> values in a data structure keeping them, for
instance, from being flattened into the surrounding list or data structure:

=for code
.say for (1, $(2,3), 4).flat; # OUTPUT: «1␤(2 3)␤4␤»
say (1, $<a b>, 2).elems; # OUTPUT: «3␤»


The itemizer operator will call the C<.item> method on the object; it can also
 be called as a subroutine. Since
L<that is a method inherited from C<Mu>|/type/Mu#method_item>, objects of any
 class can be itemized.


=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
