/
contexts.pod6
161 lines (119 loc) · 6.05 KB
/
contexts.pod6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
=begin pod :tag<perl6>
=TITLE Contexts and contextualizers
=SUBTITLE 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.
=head1 Sink X<|sink context>
I<Sink> is equivalent to 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>s, by using the
L<C<sink-all>|/routine/sink-all> method. L<Proc>s can also be
L<sunk via the C<sink> method|https://docs.perl6.org/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#Flow%29_gather_take> are explicitly
evaluated in sink context, with values returned explicitly using C<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 of them except 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> to L<Numeric>, for instance); in other cases simply an interpretation (L<IntStr> will be interpreted as L<Int> or as L<Str>).
I<Number context> is called whenever we need to apply a numerical operation on a
variable.
=begin code
my $not-a-string="1 ";
my $neither-a-string="3 ";
say $not-a-string+$neither-a-string; # OUTPUT: «4»
=end code
In the code above, strings will be interpreted in numeric context as long as
there is only some numbers 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»
=end code
In the case of I<listy> things, the numeric value will be in general equivalent
to C<.elems>; in some cases, like L<Thread|/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>
say $very-complicated-and-hairy-object; # OUTPUT: something meaningful
Or when smartmatching to a regular expression:
say 333444777 ~~ /(3+)/; # OUTPUT: «「333」 0 => 「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>, 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>|https://docs.perl6.org/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|https://docs.perl6.org/routine/~#(Operators)_infix_~>,
using 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 :skip-test<Stringification error>
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: «(exit code 1) Cannot use a Buf as a string, but you called the Stringy method on it
# in block <unit> at /tmp/bO_heb6AS9 line 1»
=end code
Since C<~> is putting in string context the second element of this list,
L<C<~>|https://docs.perl6.org/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.
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';
say $described-number; # OUTPUT: «Unity in complex plane»
C<but> creates a mixin, which endows the complex number with a C<Str> method.
C<say> puts into string context, that is, it calls C<Str>, the string
contextualizer, with the result shown above.
=end pod
# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6