Categories
Posts in this category
- Introduction
- Strings, Arrays, Hashes;
- Types
- Basic Control Structures
- Subroutines and Signatures
- Objects and Classes
- Contexts
- Regexes (also called "rules")
- Junctions
- Comparing and Matching
- Containers and Values
- Where we are now - an update
- Changes to Perl 5 Operators
- Laziness
- Custom Operators
- The MAIN sub
- Twigils
- Enums
- Unicode
- Scoping
- Regexes strike back
- A grammar for (pseudo) XML
- Subset Types
- The State of the implementations
- Quoting and Parsing
- The Reduction Meta Operator
- The Cross Meta Operator
- Exceptions and control exceptions
Sat, 27 Sep 2008
Junctions
Permanent link
NAME
"Perl 5 to 6" Lesson 07 - Junctions
SYNOPSIS
if $x eq 3|4 {
say '$x is either 3 or 4'
}
say ((2|3|4)+7).perl # (9|10|11)
DESCRIPTION
Junctions are superpositions of unordered values. Operations on junctions are executed for each item of the junction separately (and maybe even in parallel), and the results are assembled in a junction of the same type.
The junction types only differ when evaluated in boolean context. The types are any, all, one and none.
Type Infix operator
any |
one ^
all &
1 | 2 | 3 is the same as any(1..3).
my Junction $weekday = any <Monday Tuesday Wednesday
Thursday Friday Saturday Sunday>
if $day eq $weekday {
say "See you on $day";
}
In this example the eq operator is called with each pair $day, 'Monday', $day, 'Tuesday' etc. and the result is put in an any-Junction again. As soon as the result is determined (in this case, as soon as one comparison returns True) it can abort the execution of the other comparisons.
This works not only for operators, but also for subs:
if 2 == sqrt(4 | 9 | 16) {
say "YaY";
}
To make this possible, junctions stand outside the normal type hierarchy (a bit):
Object
/ \
Any Junction
/ | \
All other types
If you want to write a sub that takes a junction and doesn't autothread over it, you have to declare the type of the parameter either as Object or Junction
sub dump_yaml(Object $stuff) {
# we hope that YAML can represent junctions ;-)
....
}
A word of warning: Junctions can behave counter-intuitive sometimes. With non-junction types $a != $b and !($a == $b) always mean the same thing. If one of these variables is a junction, that might be different:
my Junction $b = 3 | 2;
my $a = 2;
say "Yes" if $a != $b ; # Yes
say "Yes" if !($a == $b); # no output
2 != 3 is true, thus $a != 2|3 is also true. On the other hand the $a == $b comparison returns a single Bool value (True), and the negation of that is False.
MOTIVATION
Perl aims to be rather close to natural languages, and in natural language you often say things like "if the result is $this or $that" instead of saying "if the result is $this or the result $that". Most programming languages only allow (a translation of) the latter, which feels a bit clumsy. With junctions Perl 6 allows the former as well.
It also allows you to write many comparisons very easily that otherwise require loops.
As an example, imagine an array of numbers, and you want to know if all of them are non-negative. In Perl 5 you'd write something like this:
# Perl 5 code:
my @items = get_data();
my $all_non_neg = 1;
for (@items){
if ($_ < 0) {
$all_non_neg = 0;
last;
}
}
if ($all_non_neg) { ... }
Or if you happen to know about List::MoreUtils
use List::MoreUtils qw(all);
my @items = get_data;
if (all { $_ >= 0 } @items) { ... }
In Perl 6 that is short and sweet:
my @items = get_data();
if all(@items) >= 0 { ... }
SEE ALSO
http://perlcabal.org/syn/S03.html#Junctive_operators =for time 1222467600 =for editor vim: spell
Comments / Trackbacks:
Trackback URL:
/blog-en/perl-5-to-6/08-junctions.trackback
Sitaram wrote
the perl 5 examples...
If efficiency is not the top priority (and thus short-circuiting is not **absolutely** required), this can also be done using the grep function (like "grep { $_ < 0 } @array", or its negation). I believe it's a lot clearer than the explicit loop in the first example and not at all different from the List::MoreUtils version in shape.
Moritz wrote
grep and junctions
I agree that, from a programmer's point of view, you can write that as a grep, no doubt. It does what you want, but it doesn't express what you want. With grep you're basically saying "search for these elements, and by using the list in scalar context count them, and tell me if there are any". Whereas with junctions you simply say "are all of these greater than zero?". We're so used to workarounds that we don't recognize them as such; Junctions don't give you some powers that you didn't have before, they just make things more natural.
Write a comment
The comments on this blog post have been disabled; the comment form below will not work.