Yep, that is pretty much it. Infix operators can make things like that confusing. For instance,
#!/usr/bin/perl use strict; use warnings; my @a = qw/a b c/; my @b = qw/d e f/; my $x = ("a", "b", "c", "d", "e", "f"); my $y = (@a, @b); my $z = (@a[0 .. $#a], @b[0 .. $#b]); print "x $x y $y z $z\n"; This prints "x f y 3 z f". What is going on is a little more clear when you look at the warnings: Useless use of a constant ("a") in void context at comma.pl line 9. Useless use of a constant ("b") in void context at comma.pl line 9. Useless use of a constant ("c") in void context at comma.pl line 9. Useless use of a constant ("d") in void context at comma.pl line 9. Useless use of a constant ("e") in void context at comma.pl line 9. Useless use of private array in void context at comma.pl line 10. Useless use of array slice in void context at comma.pl line 11. This is one of the ways you can prove that you can't have a list in scalar context. Lists flatten inside other lists (ie you can't have nested lists), but because the comma operator is being acted upon by the scalar context, you aren't getting lists, you are getting sequences. The sequence operator (a comma in scalar context) evaluates its left hand side in void context*, then its right hand side in scalar context. So, the first assignment looks like this: my $x = ("a", ("b", ("c", ("d", ("e", ("f")))))); "a" is evaluated in void context (producing a warning) then ("b", ("c", ("d", ("e", ("f")))))) is evaluated in scalar context "b" is evaluated in void context (producing a warning) then ("c", ("d", ("e", ("f"))))) is evaluated in scalar context "c" is evaluated in void context (producing a warning) then ("d", ("e", ("f"))) is evaluated in scalar context ... "f" is evaluated in scalar context (returning the value "f") The second assignment looks like this: @a is evaluated in void context (producing a warning) then @b is evaluated in scalar context (returning the number of items in @b). The third assignment is trickier to see because some commas are hidden in the expression. The slice @a[0 .. $#a] is equivalent to ($a[0], $a[1], $a[2]), so it is really: my $z = ($a[0], ($a[1], ($a[2], ($b[0], ($b[1], ($b[2])))))); And it will obviously follow the same pattern as the first assignment, which is why it returns the same thing (albeit with a slightly different warning). * this is not strictly true. In the past it has been proven that some expressions on some versions of Perl have evaluated the LHS in a context other than void, but I don't remember how to trigger that behavior, but the practical upshot is the same: only the last item in a sequence returns its value. On Wed, Oct 5, 2016 at 4:34 PM khalil zakaria Zemmoura < zemmoura.kha...@gmail.com> wrote: > I think I had a problem with my approach. I never thought about assignment > operator as returning something at all ! > When we include that parameter in the "equation" everything is clear. > > Since the list assignment is in scalar context, it returns the number of > items directly and that number is assigned to the scalar variable > > I hope I got this time 😁 > Thanks for your answers > > Le 5 oct. 2016 06:46, "Chas. Owens" <chas.ow...@gmail.com> a écrit : > > You almost have it. What you are missing is that the list assignment > operator is in scalar context and is returning the count, not the list > being assigned to. Infix operators obscure things sometimes. It is easier > to understand if we rewrite it as if list assignment was a function call > instead of an infix operator: > > my $count = list_assignment( \@lhs, \@rhs ); > > In this case, you wouldn't expect the values in @lhs to be affected in any > way by the assignment of list_assignment's return value to $count. It is > the same thing for the list assignment operator. In void context: > > ($x, $y) = qw/a b c/; > > it returns nothing, in scalar context: > > my $ret = ($x, $y, $z) = qw/a b c/; > > if returns the number of items in the RHS list (3), in list context: > > my @a = ($x, $y) = qw/a b c/; > > it returns the items that were assigned to the LHS (just "a" and "b"). > > > > > > > > > On Tue, Oct 4, 2016 at 6:48 PM zakaria <zemmoura.kha...@gmail.com> wrote: > > To summarize > > There is a list assignment and the difference between assigning to an > empty list and an non empty list is the container(s) inside the liste > that capture the different values (scalars or lists or hashes) > > for example () ans ($a, @b, %c... ) > > when we assign to an ampty list the values assigned are not captured > but the elements assigned are counted > > when we evaluate a list in scalar context, we are accessing its length. > > So i could translate this expression as following > > $s = () = get_hats_clone(); > > assigning the return value of get_hats_clone() to an empty list that > dont copy (capture) them but count them, and that assignement > '() = sub()' have a return value. > that return value when in list context is the elements of the list it > self. When in scalar context, it's the number of elements of that list > (it is empty but stored the number of all the elements returned by > get_hats_clone() > > since we are using scalar context with $s = (), then we get the number > of all the elements. > > Is that correct. > > Regards > > On Tue, 2016-10-04 at 09:14 +0000, Chas. Owens wrote: > > > > > > On Mon, Oct 3, 2016 at 10:45 PM Lawrence Statton <lawre...@cluon.com> > > wrote: > > snip > > > the =()= "operator" just does that without creating a temporary > > > variable > > snip > > > > Almost, but not quite. You can see the difference when =()= is in > > list context: > > > > my @a = (my @temp) = get_clown_hat; > > my @b = () = get_clown_hat; > > > > @a will have the items returned by get_clown_hat and @b won't. The > > assignment operators have a return value. For scalar assignment, it > > is just the scalar being assigned, regardless of the context. For > > list assignment in list context it is the list that was assigned: > > > > $ perl -E '@a = ($a, $b) = 1 .. 100; say "a is ", join ", ", @a;' > > a is 1, 2 > > $ perl -E '@a = () = 1 .. 100; say "a is ", join ", ", @a;' > > a is > > > > and the number of items on the right hand side of the assignment when > > it is in scalar context: > > > > $ perl -E '$a = () = 1 .. 100; say "a is $a"' > > a is 100 > > $ perl -E '$a = ($b) = 1 .. 100; say "a is $a"' > > a is 100 > > > > You can see how different approaches compare using the Benchmark > > module: > > > > #!/usr/bin/perl > > > > use strict; > > use Benchmark; > > use warnings; > > > > my $max_hats = 100; > > > > sub get_clown_hat { > > return (0 .. $max_hats); > > } > > > > # here, scalar context is causing the .. operator > > # to be the flip flop operator instead of the > > # range operator, so we get 1E0 instead of > > # 100 (the last item) or 101 (the count) > > # when not compared to anything, the range operator > > # compares against $. (the line number of the last > > # line read from the currently selected file handle) > > my $flip_flop_result = get_clown_hat; > > > > print "wrong result: $flip_flop_result\n"; > > > > my %subs = ( > > array => sub { > > my @a = get_clown_hat; > > return scalar @a; > > }, > > empty => sub { > > my $count = () = get_clown_hat; > > return $count; > > }, > > ); > > > > for my $sub (keys %subs) { > > print "$sub: ", $subs{$sub}(), "\n"; > > } > > > > for my $n (1_000, 10_000, 100_000) { > > $max_hats = $n; > > > > print "\n$n items\n\n"; > > Benchmark::cmpthese -2, \%subs; > > } > > > > Avoiding copying the data is about twice as fast for counting items: > > > > Use of uninitialized value $. in range (or flip) at bench.pl line 11. > > wrong result: 1E0 > > array: 101 > > empty: 101 > > > > 1000 items > > > > Rate array empty > > array 12620/s -- -52% > > empty 26457/s 110% -- > > > > 10000 items > > > > Rate array empty > > array 1310/s -- -50% > > empty 2634/s 101% -- > > > > 100000 items > > > > Rate array empty > > array 124/s -- -49% > > empty 245/s 97% -- > >