-
Notifications
You must be signed in to change notification settings - Fork 293
/
Junction.pod
95 lines (69 loc) · 3.19 KB
/
Junction.pod
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
=begin pod
=TITLE class Junction
class Junction is Mu { }
A junction is an unordered composite value of zero or more values. Junctions
I<autothread> over many operations, which means that the operation
is carried out for each junction element (also known as I<eigenstate>), and
the result is junction of the return values of all those operators.
Junctions collapse into a single value in boolean context. The semantics
depend on the I<junction type>, which can be C<all>, C<any>, C<one> or
C<none>.
=begin table
type constructor operator True if ...
==== =========== ======== ===========
all all & no value evaluates to False
any any | at least one value evaluates to True
one one ^ exactly one value evaluates to True
none none no value evaluates to True
=end table
Autothreading happens when a junction is bound to a parameter of a code object
that doesn't accept values of type C<Junction>. Instead of producing an error,
the signature binding is repeated for each value of the junction.
Example:
my $j = 1|2;
if 3 == $j + 1 {
say 'yes';
}
First autothreads over the C<< infix:<+> >> operator, producing the Junction
C<2|3>. The next autothreading step is over C<< infix:<==> >>, which produces
C<False|True>. The C<if> conditional evaluates the junction in boolean
context, which collapses it to C<True>. So the code prints C<yes\n>.
Note that the compiler is allowed to parallelize and short-circuit
autothreading (and Junction behavior in general), so it is usually an error
to autothread junctions over code with side effects.
Junctions are meant to be used as matchers in boolean context; introspection
of junctions is not supported. If you feel the urge to introspect a junction,
use a L<Set> or a related type instead.
Usage examples:
my @bool_or_int = grep Bool|Int, @list;
sub is_prime(Int $x) returns Bool {
# 'so' is for boolean context
so $x %% none(2..$x.sqrt);
}
my @primes_ending_in_1 = grep &is_prime & / 1$ /, 2..100;
say @primes_ending_in_1; # 11 31 41 61 71
Negated operators are special-cased when it comes to autothreading.
C<$a !op $b> is rewritten internally as C<!($a op $b)>. The outer
negation collapses any junctions, so the return value always a plain
L<Bool>.
my $word = 'yes';
my @negations = <no none never>;
if $word !eq any @negations {
say '"yes" is not a negation';
}
Note that without this special-casing, an expression like
C<$word ne any @words> would always evaluate to C<True> for non-trivial lists
on one side.
For this purpose, C<< infix:<ne> >> counts as a negation of C<< infix:<eq> >>.
In general it is more readable to use a positive comparison operator and
a negated junction:
my $word = 'yes';
my @negations = <no none never>;
if $word eq none @negations {
say '"yes" is not a negation';
}
=head1 See Also
=item L<http://perlgeek.de/blog-en/perl-5-to-6/08-junctions.html>
=item L<http://perl6maven.com/perl6-is-a-value-in-a-given-list-of-values>
=item L<http://perl6advent.wordpress.com/2009/12/13/day-13-junctions/>
=end pod