Scalar Reference
A mostly transparent container used for indirections
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 of #
method of(Scalar:D: --> Mu)
Returns Mu.
Returns the type constraint of the container. Example:
method default #
method default(Scalar:D: --> Str)
Returns Str.
Returns the default value associated with the container. Example:
method name #
method name(Scalar:D: --> Str)
Returns Str.
Returns the name associated with the container. Example:
method dynamic #
method dynamic(Scalar:D: --> Bool)
Returns Bool.
It will return False for scalars. Example: Note that you have to use the VAR method in order to get that information.
sub atomic-assign #
multi atomic-assign($target is rw, $value)
Performs an atomic assignment of $value into the Scalar $target. The atomic-assign routine ensures that any required barriers are performed such that the changed value will be "published" to other threads.
sub atomic-fetch #
multi atomic-fetch($target is rw)
Performs an atomic read of the value in the Scalar $target and returns the read value. Using this routine instead of simply using the variable ensures that the latest update to the variable from other threads will be seen, both by doing any required hardware barriers and also preventing the compiler from lifting reads. For example: Is certain to terminate, while in: It would be legal for a compiler to observe that $started is not updated in
sub cas #
multi cas(Mu $target is rw, Mu \expected, Mu \value)
multi cas(Mu $target is rw, &operation)
Performs an atomic compare and swap of the value in the Scalar $target. The first form has semantics like: Except it is performed as a single hardware-supported atomic instruction, as if all memory access to $target were blocked while it took place. Therefore it is safe to attempt the operation from multiple threads without any other synchronization. Since it is a reference comparison, this operation is usually
infix ⚛= #
multi infix:<⚛=>($target is rw, $value)
Performs an atomic assignment of $value into the Scalar $target. The ⚛= operator ensures that any required barriers are performed such that the changed value will be "published" to other threads.
prefix ⚛ #
multi prefix:<⚛>($target is rw)
Performs an atomic read of the value in the Scalar $target and returns the read value. Using this operator instead of simply using the variable ensures that the latest update to the variable from other threads will be seen, both by doing any required hardware barriers and also preventing the compiler from lifting reads. For example: Is certain to terminate, while in: It would be legal for a compiler to observe that $started is not updated in
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.
1 all-differ · 9 no-output · 9 ok · 2 rakupp-differs
class Scalar {}Not executed: the documentation states no expected output for this example.
say |(1,2,$(3,4)); # OUTPUT: «12(3 4)»
12(3 4)
Documentation, Rakudo and Raku++ all agree.
say |(1,2, $ = (3,4)); # OUTPUT: «12(3 4)»
12(3 4)
Documentation, Rakudo and Raku++ all agree.
my $a = 1; $a.^name.say; # OUTPUT: «Int» $a.VAR.^name.say; # OUTPUT: «Scalar» my $b := 1; $b.^name.say; # OUTPUT: «Int» $b.VAR.^name.say; # OUTPUT: «Int»
Int
Scalar
Int
Int
Int
Scalar
Int
Int
Int
Scalar
Int
Scalar
Raku++ disagrees with both the documentation and Rakudo — a defect.
my @a = 1, 2, 3; @a[0].^name.say; # OUTPUT: «Int» @a[0].VAR.^name.say; # OUTPUT: «Scalar» [1, 2, 3][0].^name.say; # OUTPUT: «Int» [1, 2, 3][0].VAR.^name.say; # OUTPUT: «Scalar» (1, 2, 3)[0].^name.say; # OUTPUT: «Int» (1, 2, 3)[0].VAR.^name.say; # OUTPUT: «Int»
Int
Scalar
Int
Scalar
Int
Int
Int
Scalar
Int
Scalar
Int
Int
Int
Int
Int
Int
Int
Int
Raku++ disagrees with both the documentation and Rakudo — a defect.
[1, $(2, 3)].raku.say; # OUTPUT: «[1, (2, 3)]» (1, $(2, 3)).raku.say; # OUTPUT: «(1, $(2, 3))»
[1, (2, 3)]
(1, $(2, 3))
Documentation, Rakudo and Raku++ all agree.
my $a = 1; my $b := $a; $b = 2; $a.say; # OUTPUT: «2»
2
Documentation, Rakudo and Raku++ all agree.
my \c = 1;
c.^name.say; # OUTPUT: «Int»
c.VAR.^name.say; # OUTPUT: «Int»
my $a = 1;
my \d = $a; # just "my \d = $ = 1" works, too
d.^name.say; # OUTPUT: «Int»
d.VAR.^name.say; # OUTPUT: «Scalar»
d = 2; # ok
c = 2; # fails
CATCH { default { put .^name, ': ', .Str } };
# OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int»Int
Int
Int
Scalar
X::Assignment::RO: Cannot modify an immutable Int
Int
Int
Int
Scalar
X::Assignment::RO: Cannot modify an immutable Int (1)
Int
Int
Int
Int
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.
cas(@a[5], $expected, $value)
Not executed: the documentation states no expected output for this example.
my Cool $x = 42; say $x.VAR.of; # OUTPUT: «(Cool)»
(Cool)
Documentation, Rakudo and Raku++ all agree.
my $x is default(666) = 42; say $x.VAR.default; # OUTPUT: «666»
666
Documentation, Rakudo and Raku++ all agree.
my $x = 42; say $x.VAR.name; # OUTPUT: «$x»
$x
Documentation, Rakudo and Raku++ all agree.
my $*FOO = 42; say $*FOO.VAR.dynamic; # OUTPUT: «True»
True
Documentation, Rakudo and Raku++ all agree.
my $s is dynamic = [1, 2, 3]; say $s.dynamic; # OUTPUT: «False» (wrong, don't do this) say $s.VAR.dynamic; # OUTPUT: «True» (correct approach)
False
True
Documentation, Rakudo and Raku++ all agree.
my $started = False;
start { atomic-assign($started, True) }
until atomic-fetch($started) { }Not executed: the documentation states no expected output for this example.
my $started = False;
start { atomic-assign($started, True) }
until $started { }Not executed: the documentation states no expected output for this example.
my $seen = $target;
if $seen<> =:= $expected<> {
$target = $value;
}
return $seen;Not executed: the documentation states no expected output for this example.
constant NOT_STARTED = Any.new;
constant STARTED = Any.new;
my $master = NOT_STARTED;
await start {
if cas($master, NOT_STARTED, STARTED) === NOT_STARTED {
say "Master!"
}
} xx 4Not executed: the documentation states no expected output for this example.
class Node {
has $.value;
has Node $.next;
}
my Node $head = Node;
await start {
for ^1000 -> $value {
cas $head, -> $next { Node.new(:$value, :$next) }
}
} xx 4;Not executed: the documentation states no expected output for this example.
my $started = False;
start { $started ⚛= True }
until ⚛$started { }Not executed: the documentation states no expected output for this example.
my $started = False;
start { $started ⚛= True }
until $started { }Not executed: the documentation states no expected output for this example.