Hi Brian (and Bruce), Just a short note to say that we had a conversation entitled "Extra . needed" on this mailing list a few weeks ago, for which the solution (per Brad Gilbert) was a sort of "double-dereferencing" (for lack of a better terminology):
https://www.nntp.perl.org/group/perl.perl6.users/2021/01/msg9605.html To my eyes there seems to be a (possibly distant) relationship between Brian's issue and Richard's issue from a few weeks ago. Anyone care to comment? And is there a unifying principle that can be distilled out...to help new (and not-so-new) users? Best, Bill. On Tue, Jan 19, 2021 at 12:27 PM Bruce Gray <robertbrucegr...@gmail.com> wrote: > > > > > On Jan 19, 2021, at 12:18 PM, Brian Duggan <bdug...@matatu.org> wrote: > > > > Hi Folks, > > > > I ran into this situation today, which seems counterintuitive: > > > > my @one = 1,2,3; > > my @two = 4,5,6; > > my @both = @one,@two; > > my @first = @both[0]; > > say @one.raku; > > say @first.raku; > > > > output: > > > > [1, 2, 3] > > [[1, 2, 3],] > > > > I was expecting @first and @one to be the same. > > I agree that @first not equalling @one is a bit counterintuitive, since the > formation of @both as a two-element array, and the extraction of its first > element, seems to be exact opposite operations. > In fact, let’s make it even more exactly opposite: > my @one = 1,2,3; > my @both; > @both[0] = @one; # Stuff it into first element > my @first = @both[0]; # Yank it out of first element > say @one.raku; > say @first.raku; > This produces the same output as your original code, even though the two > commented lines appear to cancel (like in algebra) to produce an identical > result. > > But wait! This version makes this issue clearer (at least to my > Raku-accustomed eyes). > The first commented line is a version of this: > $scalar_var = @some_array; > , in which $scalar_var _captures_ @some_array during the assignment. (Similar > to “references" in Perl: `$z = \@y;`) > To exactly invert, we need to also counteract the capturing in the second > commented line. > (continued below) > > > I discovered that I could instead write either of these -- > > > > my (@first) = @both[0]; > > my @first := @both[0]; > > > > or I could change the @both assignment to be > > > > my @both := @one, @two; > > To discuss those three alternatives, let’s extend your original code: > my @one = 1,2,3; > my @two = 4,5,6; > my @both = @one,@two; > my @first = @both[0]; > say @one.raku; > say @first.raku; > > my (@a) = @both[0]; > my @b := @both[0]; > my @both_bound := @one,@two; > my @c := @both_bound[0]; > say .raku for @a, @b, @c; # They all look right, but only because > nothing wrote to them. > @a[1] = 7; say @one; # [1 2 3] , independent as expected > @b[1] = 8; say @one; # [1 8 3] , bound/aliased! > @c[1] = 9; say @one; # [1 9 3] , bound/aliased! > > The first form, `my (@array) = …`, I read as quite clever (as in “I didn’t > think of it myself”). it does what I think you intended. > Our community is still in the idiom-forming phase, but this would not be a > preferred form for me. > I think that is (mostly?) due to it being a LHS-manipulation, so it cannot > easily work as part of a larger expression without some temp array on the > left-hand side. > [ > I admit that part of my dislike is because it looks too much like > this from Perl: > my ($only_want_the_first_element) = @some_array; > , and having a @-sigiled variable inside that expression looks like a > a redundant use of parens. > Please give zero weight to that biased part of my assessment. > ] > > The second and third forms both use “binding”, which would be fine if “live > links” between @one and @first was your need and intention, but would be a > source of bugs otherwise. > Your original code looks like you want @first to contain independent copies > of the @one elements. > If I were refactoring your code, I would not assume that changing assignment > to binding would be OK to do. > (I suspect that you already knew that, and were just showing us all of the > variants that “worked”) > > > ..but I wonder if there's an idiomatic approach -- or > > way of thinking about this -- that makes this flow more > > intuitive. > > (continued from above) > I would probably write it as: > my @first = @both[0].list; > , but for this exact case I might instead say: > my @first = @( @both[0] ); > . They do the same thing here, and both look idiomatic to me, > but .list looks like an action/command to @both[0], > and @(...) is the List Contextualizer, > so which one I would use would depend on the surrounding code, > and who I expected to be reading the code. > https://docs.raku.org/type/Any#index-entry-@_list_contextualizer > > So, I recommend .list or @(…) as more intuitive, maybe even *sufficiently* > intuitive :^) > > > thanks > > Brian > > — > Hope this helps, > Bruce Gray (Util of PerlMonks) >