Rules / Types, classes & roles / basic

Junction Reference

Logical superposition of values

What it is #

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

method new #

multi method new(Junction: \values, Str :$type!)
multi method new(Junction: Str:D \type, \values)

These constructors build a new junction from the type that defines it and a set of values. The main difference between the two multis is how the type of the Junction is passed as an argument; either positionally as the first argument, or as a named argument using type.

method defined #

multi method defined(Junction:D:)

Checks for definedness instead of Boolean values. Failures are also considered non-defined: Since 6.d, this method will autothread.

method Bool #

multi method Bool(Junction:D:)

Collapses the Junction and returns a single Boolean value according to the type and the values it holds. Every element is transformed to Bool. All elements in this case are converted to True, so it's false to assert that only one of them is. Just one of them is truish in this case, 1, so the coercion to Bool returns True.

method Str #

multi method Str(Junction:D:)

Autothreads the .Str method over its elements and returns results as a Junction. Output methods that use .Str method (print and put) are special-cased to autothread junctions, despite being able to accept a Mu type.

method iterator #

multi method iterator(Junction:D:)

Returns an iterator over the Junction converted to a List.

method gist #

multi method gist(Junction:D:)

Collapses the Junction and returns a Str composed of the type of the junction and the gists of its components:

method raku #

multi method raku(Junction:D:)

Collapses the Junction and returns a Str composed of raku of its components that evaluates to the equivalent Junction with equivalent components:

infix C<~> #

multi infix:<~>(Str:D $a, Junction:D $b)
multi infix:<~>(Junction:D $a, Str:D $b)
multi infix:<~>(Junction:D \a, Junction:D \b)

The infix ~ concatenation can be used to merge junctions into a single one or merge Junctions with strings. The resulting junction will have all elements merged as if they were joined into a nested loop: On the other hand, the versions of ~ that use a string as one argument will just concatenate the string to every member of the Junction, creating another Junction with the same number of elements.

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

3 all-differ · 10 no-output · 14 ok · 1 rakupp-differs

class Junction is Mu { }

Not executed: the documentation states no expected output for this example.

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

Not executed: the documentation states no expected output for this example.

say so 3 == (1..30).one;         # OUTPUT: «True␤»
say so ("a" ^ "b" ^ "c") eq "a"; # OUTPUT: «True␤»
Output
True
True

Documentation, Rakudo and Raku++ all agree.

my $j = 1|2;
if 3 == $j + 1 {
    say 'yes';
}

Not executed: the documentation states no expected output for this example.

my %h = :42foo, :70bar;
say    %h{one <foo meow>}:exists; # OUTPUT: «one(True, False)␤»
say so %h{one <foo meow>}:exists; # OUTPUT: «True␤»
say    %h{one <foo  bar>}:exists; # OUTPUT: «one(True, True)␤»
say so %h{one <foo  bar>}:exists; # OUTPUT: «False␤»
Documentation
one(True, False)
True
one(True, True)
False
Rakudo
True
True
False
False
Raku++
(True False)
True
(True True)
True

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

(1..3).head( 2|3 ).say; # OUTPUT: «any((1 2), (1 2 3))␤»
Output
any((1 2), (1 2 3))

Documentation, Rakudo and Raku++ all agree.

'walking on sunshine'.contains( 'king'&'sun' ).say; # OUTPUT: «all(True, True)␤»
Output
all(True, True)

Documentation, Rakudo and Raku++ all agree.

if a() | b() | c() {
say "At least one of the routines was called and returned a truthy value"
}

Not executed: the documentation states no expected output for this example.

my @list = <1 2 "Great">;
@list.append(True).append(False);
my @bool_or_int = grep Bool|Int, @list;

Not executed: the documentation states no expected output for this example.

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;        # OUTPUT: «[11 31 41 61 71]␤»
Output
[11 31 41 61 71]

Documentation, Rakudo and Raku++ all agree.

my @exclude = <~ .git>;
for dir(".") { say .Str if .Str.ends-with(none @exclude) }

Not executed: the documentation states no expected output for this example.

my @a = ();
say so all(@a) # True, because there are 0 Falses

Not executed: the documentation states no expected output for this example.

my @a = ();
say so @a && all(@a);   # OUTPUT: «False␤»
Output
False

Documentation, Rakudo and Raku++ all agree.

my $word = 'yes';
my @negations = <no none never>;
if $word !eq any @negations {
    say '"yes" is not a negation';
}

Not executed: the documentation states no expected output for this example.

my $word = 'yes';
my @negations = <no none never>;
if $word eq none @negations {
    say '"yes" is not a negation';
}

Not executed: the documentation states no expected output for this example.

my $j = +any "not a number", "42", "2.1";
my @list = gather for $j -> $e {
    take $e if $e.defined;
}
@list.say; # OUTPUT: «[42 2.1]␤»
Documentation
[42 2.1]
Rakudo
[any((HANDLED) Cannot convert string to number: base-10 number must begin with valid digits or '.' in '<HERE>not a number' (indicated by <HERE>)
, 42, 2.1)]
Raku++
[3]

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

my $j = +any "not a number", "42", "2.1";
try say $j == 42;
$! and say "Got exception: $!.^name()";
# OUTPUT: «Got exception: X::Str::Numeric␤»
Documentation
Got exception: X::Str::Numeric
Rakudo
Got exception: X::Str::Numeric
Raku++
False

Raku++ disagrees with both the documentation and Rakudo — a defect.

sub calc ($_) { die when 13 }
my $j = any 1..42;
say try calc $j; # OUTPUT: «Nil␤»
Output
Nil

Documentation, Rakudo and Raku++ all agree.

sub calc ($_) { die when 13 }
my $j = any 1..42;
$j = any (gather $j».take).grep: {Nil !=== try calc $_};
say so $j == 42; # OUTPUT: «True␤»
Output
True

Documentation, Rakudo and Raku++ all agree.

say 25 == (25 | 42);    # OUTPUT: «any(True, False)␤» – Junction
say 25 ~~ (25 | 42);    # OUTPUT: «True␤»             – Bool
Output
any(True, False)
True

Documentation, Rakudo and Raku++ all agree.

my $j = Junction.new(<Þor Oðinn Loki>, type => "all");
my $n = Junction.new( "one", 1..6 )

Not executed: the documentation states no expected output for this example.

say ( 3 | Str).defined ;   # OUTPUT: «True␤»
say (one 3, Str).defined;  # OUTPUT: «True␤»
say (none 3, Str).defined; # OUTPUT: «False␤»
Output
True
True
False

Documentation, Rakudo and Raku++ all agree.

my $foo=Failure.new;
say (one 3, $foo).defined; # OUTPUT: «True␤»
Output
True

Documentation, Rakudo and Raku++ all agree.

my $n = Junction.new( "one", 1..6 );
say $n.Bool;                         # OUTPUT: «False␤»
Output
False

Documentation, Rakudo and Raku++ all agree.

my $n = Junction.new( "one", <0 1> );
say $n.Bool;                         # OUTPUT: «True␤»
Output
True

Documentation, Rakudo and Raku++ all agree.

<a 42 c>.all.say; # OUTPUT: «all(a, 42, c)␤»
Output
all(a, 42, c)

Documentation, Rakudo and Raku++ all agree.

<a 42 c>.all.raku.put; # OUTPUT: «all("a", IntStr.new(42, "42"), "c")␤»
Output
all("a", IntStr.new(42, "42"), "c")

Documentation, Rakudo and Raku++ all agree.

my $odd  = 1|3|5;
my $even = 2|4|6;

my $merged = $odd ~ $even;
say $merged; # OUTPUT: «any(12, 14, 16, 32, 34, 36, 52, 54, 56)␤»

say "Found 34!" if 34 == $merged; # OUTPUT: «Found 34!␤»
my $prefixed = "0" ~ $odd;
say "Found 03" if "03" == $prefixed; # OUTPUT: «Found 03!␤»

my $postfixed = $odd ~ "1";
say "Found 11" if 11 == $postfixed; # OUTPUT: «Found 11!␤»
Documentation
any(12, 14, 16, 32, 34, 36, 52, 54, 56)
Found 34!
Found 03!
Found 11!
Rakudo
any(12, 14, 16, 32, 34, 36, 52, 54, 56)
Found 34!
Found 03
Found 11
Raku++
any(any(12, 14, 16), any(32, 34, 36), any(52, 54, 56))
Found 34!
Found 03
Found 11

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.