3

new to Perl, and I found Perl scalar and list quite confusing.

At code below,

$a = ("a", "b", "c");

print "$a \n";

the result will be "c"

But if I give name to the array

@arr = ("a", "b", "c");
$a = @arr;

print "$a \n";

the result is 3, which is the number of element

I think the secound one is specification, but I don't get the logic why it returns "c" on the first one.

Rioma
  • 31
  • 2
  • 3
    I think you also [asked this on /r/perl](https://www.reddit.com/r/perl/comments/100ds0d/why_it_returns_last_element_of_array/). That's fine, but it's courteous to tell people that. I have my answer there, but I'll also point people the [perlfaq4: What's the difference between a list and an array](https://perldoc.perl.org/perlfaq4#What-is-the-difference-between-a-list-and-an-array?). @ikegami's answer has the other links that are enlightening. – brian d foy Jan 01 '23 at 13:17
  • 1
    Always enable warnings! – ysth Jan 01 '23 at 23:15
  • As a beginner, I often found checking `scalar` of an expression helpful for debugging when I was confused, e.g. `scalar(@array)` – Supertech Jan 03 '23 at 18:44

2 Answers2

5

Context affects what operators return.


@arr = ("a", "b", "c");

This is a list assignment operator because left-hand side of the = "looks listy". The list assignment operator evaluates its right-hand side in list context.

The comma operator in list context evaluates each operand in list context, and produces the all the scalars produced by its operands.


$a = @arr;

This is a scalar assignment operator because left-hand side of the = "doesn't look listy". The scalar assignment operator evaluates its right-hand side in scalar context.

An array in scalar context produces the number of elements in the array.


$a = ("a", "b", "c");

This is a scalar assignment operator because left-hand side of the = "doesn't look listy". The scalar assignment operator evaluates its right-hand side in scalar context.

The comma operator in scalar context evaluates all but the last operand in void context, then it evaluates the last operand in scalar context. It produces the scalar produced by this last operand.

This means that

EXPR, EXPR2, EXPR3           # In scalar context

is similar to

do { EXPR; EXPR2; EXPR3 }    # In scalar context

(Just no lexical scope.)


Ref:

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I think I'd say "in scalar context evaluates all but the *expression*", and so on in that para. I knew a lot of old C guys that would use the scalar comma for side effects, because I guess they didn't like semicolons. – brian d foy Jan 01 '23 at 13:20
  • 1
    Also, [blast from the past](https://stackoverflow.com/a/8235148/2766176) – brian d foy Jan 01 '23 at 13:22
  • 1
    Heh, also this perlmonks [blast from the past](https://perlmonks.org/?node_id=719187) – brian d foy Jan 01 '23 at 13:29
  • 1
    You should definitely mention the warnings they ought to have gotten – ysth Jan 01 '23 at 23:16
1

Summary on array usage

use strict;
use warnings;
use feature 'say';

my @array     = ( 'a', 'b', 'c', 'd' );
my $aref      = [ 'a', 'b', 'c', 'd' ];
my $elem      = ( 'a', 'b', 'c', 'd' );
my $last      = @array[-1];
my @slice     = @array[0,2..3];
my $count     = scalar @array;
my $index_max = $#array;

say "
    \@array     = @array        array
    \$aref      = $aref         array reference (holds address of anonymous array)
    \$elem      = $elem         last element of array (useless void context warnings)
    \$last      = $last         last element of array
    \@slice     = @slice        array slice 
    \$count     = $count        count array elements
    \$index_max = $index_max    max array index
    
    Note: array index starts with 0
";

Output

Useless use of a constant ("a") in void context at C:\temp\work\perl\examples\array_demo.pl line 7.
Useless use of a constant ("b") in void context at C:\temp\work\perl\examples\array_demo.pl line 7.
Useless use of a constant ("c") in void context at C:\temp\work\perl\examples\array_demo.pl line 7.

        @array     = a b c d            array
        $aref      = ARRAY(0x107a790)   array reference (holds address of anonymous array)
        $elem      = d                  last element of array (useless void context warnings)
        $last      = d                  last element of array
        @slice     = a c d              array slice
        $count     = 4                  count array elements
        $index_max = 3                  max array index

        Note: array index starts with 0

A few array tutorials:

Polar Bear
  • 6,762
  • 1
  • 5
  • 12
  • 3
    Fun fact: none of your reference mention the comma operator in scalar context, which is what the question was about. – Dada Jan 01 '23 at 15:19
  • Yes, but OP doesn't know how it works and he thinks that it is an array (what is wrong). He needs to get know Perl's documentation -- in added description I mention only final result (not what his code performs). – Polar Bear Jan 01 '23 at 21:09