Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Really binding an argument to a parameter? (Perl6)

The Perl6 docs state "By default, parameters are bound to their argument and marked as read-only." But running the following code:

# Example 1
sub f1 ( $x ) { say $x.VAR.WHAT; say $x.WHAT; say $x }
f1(1);

yields:

(Scalar)
(Int)
1

while this code:

# Example 2
my $y := 1;
say $y.VAR.WHAT; say $y.WHAT; say $y;

yields:

(Int)
(Int)
1

It's the (Scalar) in the output of Example1 that I do not understand: why is there a Scalar when I supposedly bind the Int 1 - argument to the identifier $x ? It seems as if the value 1 got "assigned" to $x, rather than "bound".

like image 758
ozzy Avatar asked Jun 22 '19 12:06

ozzy


1 Answers

Scalar containers are also used to indicate items, and thus prevent flattening of them. In the absence of a type constraint, the implementation will conservatively wrap the incoming argument into a read-only Scalar container to avoid any unexpected flattening taking place. Contrast this:

sub foo($x) {
    my @a = $x;
    say @a.elems;
}
foo([1,2,3]);

Which outputs 1 (no flattening), with a sigilless binding:

sub foo(\x) {
    my @a = x;
    say @a.elems;
}
foo([1,2,3])

Which outputs 3, since no item context is imposed. Were the Scalar container not there, both would output 3.

In the presence of a non-Iterable type constraint, this wrapping will be omitted. Thus writing:

sub f1(Int $x) {
    say $x.VAR.WHAT;
    say $x.WHAT;
    say $x
}
f1(1)

Will output:

(Int)
(Int)
1

With .VAR simply yielding identity on a non-container.

like image 161
Jonathan Worthington Avatar answered Nov 19 '22 14:11

Jonathan Worthington