Skip Menu |
Report information
Id: 128842
Status: open
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: zefram [at] fysh.org
Cc:
AdminCc:

Severity: (no value)
Tag: Bug
Platform: (no value)
Patch Status: (no value)
VM: (no value)



Date: Thu, 4 Aug 2016 18:26:37 +0100
To: rakudobug [...] perl.org
Subject: [BUG] := inconsistent semantics
From: Zefram <zefram [...] fysh.org>
Download (untitled) / with headers
text/plain 1.4k
Show quoted text
> sub ss0(Scalar $s, $nv) { my $v := $s; $v = $nv }
sub ss0 (Scalar $s, $nv) { #`(Sub|76872624) ... } Show quoted text
> my $a = 3
3 Show quoted text
> ss0($a.VAR, 5)
5 Show quoted text
> $a
5 Show quoted text
> sub ss1($s, $nv) { my $v := $s; $v = $nv }
sub ss1 ($s, $nv) { #`(Sub|76873232) ... } Show quoted text
> ss1($a.VAR, 7)
Cannot assign to a readonly variable or a value Show quoted text
> $a
5 In the above, the := binding operator exhibits two very different behaviours. In ss0() its effect is to set the container of its lhs to be the value of its rhs. This is used to modify the value stored in the container that was passed in as a parameter. In ss1() the same code doesn't work. Based on behaviour I've seen from the binding operator in other contexts, I think here its effect is to set the container of its lhs to be the *container* of its rhs. The documentation doesn't admit to this double meaning of the binding operator. doc/Language/operators.pod describes only the second behaviour. I would expect := to have consistent semantics, unaffected by parameter type constraints. I'm not sure which semantic is intended. The first is very useful, and needs to be available somehow. I have not found any other way of accessing the content of a Scalar container from a reference to the container, but maybe I missed something. The second semantic can always be achieved in terms of the first, by adding an explicit ".VAR" to the rhs. I have only ever wanted the first semantic, but I take no position on Huffman coding. -zefram
To: perl6-compiler [...] perl.org
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Date: Thu, 4 Aug 2016 19:51:54 +0200
From: Timo Paulssen <timo [...] wakelift.de>
Download (untitled) / with headers
text/plain 538b
The := operator only has one behaviour/semantics in this example. However, in one of your examples you're actually getting a Scalar inside a Scalar. Check this out: timo@schmand ~> perl6 -e 'my $a = 3; sub ss1(Scalar $s, $nv) { say $s.VAR.DUMP }; ss1($a.VAR, 7)' ▶3 timo@schmand ~> perl6 -e 'my $a = 3; sub ss1($s, $nv) { say $s.VAR.DUMP }; ss1($a.VAR, 7)' ▶▶3 Does that help clear things up a little? I'm not sure what mechanism causes the example where Scalar is supplied in the signature to not re-containerize, though.
From: Zefram <zefram [...] fysh.org>
Date: Thu, 4 Aug 2016 19:09:09 +0100
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
To: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
Timo Paulssen via RT wrote: Show quoted text
>However, in one of your examples you're actually getting a Scalar inside >a Scalar. Check this out:
Huh, there is indeed a difference there that I wasn't aware of. Thanks. Can also be seen by: Show quoted text
> sub tt0(Scalar $s) { say $s.WHAT; }
sub tt0 (Scalar $s) { #`(Sub|69930648) ... } Show quoted text
> sub tt1($s) { say $s.WHAT; }
sub tt1 ($s) { #`(Sub|69930800) ... } Show quoted text
> my $a = 3
3 Show quoted text
> tt0($a.VAR)
(Int) Show quoted text
> tt1($a.VAR)
(Scalar) Show quoted text
>
In this respect, tt1() is behaving the way I expect, and tt0() looks like a bug. The sub is receiving, as the apparent value of the parameter, the value contained in what the caller thought it was sending as the parameter value. So what I'd perceived as useful behaviour of := seems to be a bug in parameter handling. This issue has some slight resemblance to [perl #128409] and [perl #128407], but probably isn't the same bug as either. Is there some way I missed to get access to the content of a Scalar? Something other than exploiting this bug? That's what I was originally after when I ran into this. -zefram
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
To: perl6-compiler [...] perl.org
From: Timo Paulssen <timo [...] wakelift.de>
Date: Thu, 4 Aug 2016 20:26:59 +0200
Download (untitled) / with headers
text/plain 446b
On 04/08/16 20:09, Zefram wrote: > Is there some way I missed to get access to the content of a Scalar? > Something other than exploiting this bug?  That's what I was > originally after when I ran into this. > > -zefram

Aye, you can .<> the value to "decont" it, which will give you the content of the container. If there's another container in it (like with the thing that dumps as ▶▶3), you'll want to .<>.<> to get the value itself.
Date: Thu, 4 Aug 2016 19:31:55 +0100
From: Zefram <zefram [...] fysh.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
To: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
Download (untitled) / with headers
text/plain 315b
Timo Paulssen via RT wrote: Show quoted text
>Aye, you can .<> the value to "decont" it,
Doesn't work as an lvalue: Show quoted text
> my $a = 3
3 Show quoted text
> my $b = $a.VAR
3 Show quoted text
> $b.WHAT.say
(Scalar) Show quoted text
> $b.<>.WHAT.say
(Int) Show quoted text
> $b.<> = 5
Cannot modify an immutable Int in block <unit> at <unknown file> line 1 Has some value for reading, at least. -zefram
Date: Thu, 4 Aug 2016 20:37:31 +0200
From: Timo Paulssen <timo [...] wakelift.de>
To: perl6-compiler [...] perl.org
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Download (untitled) / with headers
text/plain 430b
On 08/04/2016 08:31 PM, Zefram wrote: Show quoted text
> Timo Paulssen via RT wrote:
>> Aye, you can .<> the value to "decont" it,
> Doesn't work as an lvalue:
That should be very obvious; I may have communicated less-than-effectively. You can only assign to a Scalar. You just used .<> to get rid of the Scalar and get the Value itself, which then can't be assigned to (because it's no longer tied to a storage location that could be changed).
Date: Thu, 4 Aug 2016 19:47:39 +0100
From: Zefram <zefram [...] fysh.org>
To: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Download (untitled) / with headers
text/plain 445b
Timo Paulssen via RT wrote: Show quoted text
>You can only assign to a Scalar.
How? Specifically, in the situation where I have a Scalar as a value, stored in a variable or as a sub parameter. How do I assign into it? The usual assignment operator, if applied to the variable or parameter, assigns to that variable (or fails to assign to the parameter). It shouldn't do otherwise, of course. Some other operator is required to store into a Scalar. -zefram
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
To: perl6-compiler [...] perl.org
Date: Thu, 4 Aug 2016 22:00:27 +0200
From: Timo Paulssen <timo [...] wakelift.de>
Download (untitled) / with headers
text/plain 1008b
On 08/04/2016 08:47 PM, Zefram wrote: Show quoted text
> Timo Paulssen via RT wrote:
>> You can only assign to a Scalar.
> How? Specifically, in the situation where I have a Scalar as a value, > stored in a variable or as a sub parameter. How do I assign into it? > The usual assignment operator, if applied to the variable or parameter, > assigns to that variable (or fails to assign to the parameter). > It shouldn't do otherwise, of course. Some other operator is required > to store into a Scalar. > > -zefram
Well, assignment is implemented by calling .STORE on the scalar. Don't forget that unless you "is rw" or "is raw" a parameter, you'll get a new scalar that has the same value, but won't allow you to write to it. (using a sigil-less parameter is equivalent to "is raw"). It was not correct to say "only assign to scalars", as there's also LexicalRef, NativeRef, Proxy, ... The assignment operator is the operator to store into a Scalar. I'm getting the feeling we're not getting through to each other :)
From: Zefram <zefram [...] fysh.org>
Date: Thu, 4 Aug 2016 21:36:18 +0100
To: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Download (untitled) / with headers
text/plain 1.4k
Timo Paulssen via RT wrote: Show quoted text
>Well, assignment is implemented by calling .STORE on the scalar.
That's not usable in the way I'd expect: Show quoted text
> my $a = 3
3 Show quoted text
> my $b = $a.VAR
3 Show quoted text
> $b.STORE(5)
Cannot modify an immutable Int in block <unit> at <unknown file> line 1 Show quoted text
>The assignment operator is the operator to store into a Scalar.
The assignment operator requires an lvalue on its lhs. Where I have a Scalar as an rvalue, I don't know how to make an lvalue from it. Show quoted text
>I'm getting the feeling we're not getting through to each other :)
Yeah. Let me try to make it clearer. In the above situation, with a reference to $a's Scalar container in $b, I'd like to achieve what the assignment "$a = 5" would, but by an operation using $b and not directly mentioning $a. The result should be that $b is unchanged (still referencing $a's container) and $a subsequently has the value 5. Equivalent Perl 5: $ perl -lwe '$a = 3; $b = \$a; $$b = 5; print $a' 5 "$b = 5", unsurprisingly, doesn't achieve it: that leaves $a untouched, and changes $b so that it no longer references $a's container. Using the code from my initial message on this ticket, "ss0($b, 5)" achieves what I want, but apparently that's only due to the parameter handling bug that you identified. I'd like a way that doesn't depend on exploiting a bug. The answer could well look somewhat like either "$b.STORE(5)" (a method on the Scalar object) or "$b.<> = 5" (making an lvalue from the Scalar object), though as we've seen neither of these is correct. -zefram
To: Zefram <zefram [...] fysh.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
CC: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
From: "Patrick R. Michaud" <pmichaud [...] pobox.com>
Date: Thu, 4 Aug 2016 15:50:42 -0500
Download (untitled) / with headers
text/plain 578b
On Thu, Aug 04, 2016 at 09:36:18PM +0100, Zefram wrote: Show quoted text
> Yeah. Let me try to make it clearer. In the above situation, with > a reference to $a's Scalar container in $b, I'd like to achieve what > the assignment "$a = 5" would, but by an operation using $b and not > directly mentioning $a. The result should be that $b is unchanged > (still referencing $a's container) and $a subsequently has the value 5.
So are you looking for...? my $a = 3; my $b := $a; # $b is bound to $a $b = 5; # Assign 5 to $b (which is also $a) say $a; # "5" Pm
From: Zefram <zefram [...] fysh.org>
Date: Thu, 4 Aug 2016 21:54:54 +0100
To: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Download (untitled) / with headers
text/plain 304b
Patrick R. Michaud wrote: Show quoted text
>So are you looking for...?
No. I want a writable reference that I can pass around as a value, store in a data structure, and so on. The Scalar object obtained by "$a.VAR" is clearly the thing to pass around as a value; I'm looking for the way to write through it. -zefram
CC: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
From: "Patrick R. Michaud" <pmichaud [...] pobox.com>
Date: Thu, 4 Aug 2016 16:35:01 -0500
To: Zefram <zefram [...] fysh.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Download (untitled) / with headers
text/plain 1.1k
On Thu, Aug 04, 2016 at 09:54:54PM +0100, Zefram wrote: Show quoted text
> Patrick R. Michaud wrote:
> >So are you looking for...?
> > No. I want a writable reference that I can pass around as a value, > store in a data structure, and so on. The Scalar object obtained by > "$a.VAR" is clearly the thing to pass around as a value; I'm looking > for the way to write through it.
"writable reference" --> "Scalar" "store in a data structure" --> "bind using :=" I think that using := is the canonical way to do these sorts of operations: Show quoted text
> my $a = 123;
123 Show quoted text
> my $b := $a; $b = 5; say $a;
5 Show quoted text
> my @c; @c[2] := $a; $a = 5; say @c[2];
5 Show quoted text
> my %d; %d<abc> := $a; $a = 'abc'; say %d<abc>;
abc Show quoted text
> say "$a $b @c[2] %d<abc>";
abc abc abc abc Show quoted text
> $a = 4; say "$a $b @c[2] %d<abc>"
4 4 4 4 More generally -- when I last checked Perl 6 doesn't really have "references" in the same style as Perl 5 -- i.e., objects that can be passed around and are magically transparent when you need them to be and opaque when you don't. So far I think we've been able to use binding to do all of the things that Perl 5 references allowed (but more cleanly and efficiently). Pm
Date: Thu, 4 Aug 2016 23:25:48 +0100
From: Zefram <zefram [...] fysh.org>
To: Timo Paulssen via RT <perl6-bugs-followup [...] perl.org>
Subject: Re: [perl #128842] [BUG] := inconsistent semantics
Download (untitled) / with headers
text/plain 3.1k
Patrick R. Michaud wrote: Show quoted text
>"store in a data structure" --> "bind using :="
That's not going to pass well through anything that treats the data as values. For example, after your Show quoted text
>> my @c; @c[2] := $a; $a = 5; say @c[2];
>5
if I then do my @d = @c.map({ $_ }) then @d[2] is not an alias of @c[2] or $a. It's also quite inconvenient to bind into a data structure like that. The actual code I'm working on at the moment has the form my $flange_width; my $farthingale_height; my @computations = ( { output_loc => $flange_width.VAR, formula => "aaa" }, { output_loc => $farthingale_height.VAR, formula => "bbb" }, ); loop { # ... for @computations { # some computation using $_<formula> if $got_it { write_to($_<output_loc>, $result); } } } # later code uses $flange_width and $farthingale_height There are multiple computations to perform, which are done by similar processes, and they benefit from partial computations being interleaved. So they benefit from the partial computations being described by an array that's looped over. But once it's done, the final outputs are treated quite individually. To do this with := means that I can't create @computations in a neat table like that, with each entry self-contained. I'd have to do something like my @computations = ( { formula => "aaa" }, { formula => "bbb" }, ); @computations[0]<output> := $flange_width; @computations[1]<output> := $farthingale_height; Note that related items (output location and formula, for a particular computation) are now separated. The .VAR version had the nice feature that the reference, being an ordinary value, can be mentioned inline in the constructor expression. I suppose I could add an extra level of data structure: create a one-element array and bind my target into it, then use that array as my valueish reference. The array can be passed around by value, put into a data structure, and so on. Something like sub ref_to(Mu $a is rw) { my @s; @s[0] := $a; @s } sub read_ref(@s) { @s[0] } sub write_ref(@s, Mu $nv) { @s[0] = $nv } my $a = 3; my $b = ref_to($a); write_ref($b, 5); But that seems perverse, when the Scalar object itself is visible to the language. In principle the Scalar object is exactly what I'm after; it's just missing a write method. Show quoted text
>More generally -- when I last checked Perl 6 doesn't really have >"references" in the same style as Perl 5
I'm not particularly looking for the same style. I'm looking for the basic ability. In Perl 5 it's done by reference scalars, in C it's done by pointers; it is surprising that Perl 6 would not support this paradigm. Show quoted text
>magically transparent when you need them to be
I'm not clear what you're referring to here. The way I interpret those words, Perl 5 references are never magically transparent: there is always an explicit distinction between the reference and the referent. (Except for the now-removed experimental autoderef feature on a few builtins.) Perl 6, on the other hand, frequently has operations silently pass through a container. (Named method calls on the Scalar, where not handled by the Scalar class, used to be passed through to the contained value, but that seems to have stopped working.) -zefram


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org