在perl中将数组赋值给标量时的行为如何?

1dkrff03  于 2023-08-06  发布在  Perl
关注(0)|答案(3)|浏览(169)

我的代码是:

my $r = ['111','222','aaa','bbb'];
print $r;
my $s = ('111','222','aaa','bbb');
print $s;

字符串
我能理解的第一个打印,$r将是一个引用,打印给我类似ARRAY(0x44444444)的东西。
但是我不明白为什么第二个例子print $s给出了最后一个元素bbb,但是为什么呢?

ql3eal8s

ql3eal8s1#

逗号运算符,的功能取决于上下文。需要考虑列表上下文和标量上下文。
在列表上下文中,逗号运算符分隔列表中的项。如果左侧是数组或括在括号中,则赋值将列表上下文强加在右侧:

my ($s) = (1, 2, 3);  #=> $s = 1, rest discarded
(my $s) = (1, 2, 3);  # the same
my @arr = (1, 2, 3);  #=> @arr = (1, 2, 3)

字符串
在标量上下文中,Perl希望我们提供单个值。逗号运算符的工作方式与C或其他语言中的一样:计算所有表达式并丢弃它们的值。仅保留最后一个值:

my $s = (1, 2, 3);  #=> $s = 3, previous items discarded


参见:perldoc perlop中的逗号运算符
请注意,括号(...)不会创建数组。它们仅用于控制优先级。在$s = (1, 2, 3)中需要数组,因为$s = 1, 2, 3将被解析为($s = 1), 2, 3

nmpmafwu

nmpmafwu2#

这里有几件事情,其中大部分都在Intermediate Perl中介绍过。
首先,[]大括号创建一个数组引用,所有引用都是标量。将引用赋值给标量就是将标量赋值给标量。当你输出这个时,你会看到引用的字符串化:ARRAY(0x44444444)。每当你给予打印的东西,它会根据它使用的任何规则来约束自己:引用显示它们的类型和内部(非物理)存储器地址。
其次,Perl根据它在左边看到的内容来决定如何处理赋值的右边。在这两个赋值语句中,左边都有一个标量,因此Perl选择标量语义。一般来说,Perl更关心“动词”而不是“名词”,这是许多主流语言的一个转变,这些语言根据您拥有的(特定的对象标识)而不是您正在使用它做什么来选择它们的操作。
这里棘手的部分是,许多人从来没有花时间弄清楚数组和列表之间的区别,所以有很多可怕的解释。
这是什么

('111','222','aaa','bbb')

字符串
在Perl中,我们还不知道,因为我们没有上下文。从人类的Angular 来看,这看起来像一个列表。它有几个元素,它周围有括号,在编程之外,这就是我们所说的列表。但这并不是编程之外的事情,每种语言都对一些想法非常特别,以至于我们对这些想法的日常使用无法翻译。(这是学习任何语言教程的最有力论据之一,不仅要学习它的语法,还要学习它的基本概念)。
但是,回到Perl表达式('111','222','aaa','bbb')。它漂浮在以太中,等待着某个东西给予它它所需要的额外上下文。
foreach中,Perl使用列表上下文,因为这就是foreach所做的:

foreach my $item ( ('111','222','aaa','bbb') ) { ... }


赋值给数组会强制执行列表上下文,因为这就是它的作用:

my @array = ('111','222','aaa','bbb');


创建数组引用的过程是一样的:

[ ('111','222','aaa','bbb') ]


在Perl中,你必须知道你有什么上下文。一开始会有点奇怪,但你会习惯的。
现在,有一些东西不使用列表上下文,您已经发现了其中之一。将此表达式赋值给标量使用标量上下文,因为当左边是标量时,赋值运算符就是这样做的:

my $s = ('111','222','aaa','bbb');  # not a list!


Perl在标量上下文中如何处理逗号?它是same thing that C comma operator does。它计算最左边的表达式,放弃结果,计算右边的表达式,然后返回结果。如果有几个逗号,右边的结果将成为下一个逗号的左边表达式。最后,在系列的最后,您将得到已计算的表达式。
在这个例子中,这似乎很愚蠢,但考虑一些更复杂的事情。这些子表达式中的每一个都可能具有副作用。在此示例中,每个子表达式设置现有变量的值:

use v5.10;

my( $dog, $cat, $bird );
say join "\n", "---Start", "Dog: $dog", "Cat: $cat", "Bird: $bird";

my $s = ( $dog = 'Snoopy',  $cat = 'Garfield', $bird = 'Woody' );
say join "\n", "---End", "Dog: $dog", "Cat: $cat", "Bird: $bird";
say "\ns is $s";


输出显示变量在标量上下文中作为逗号运算符的结果获得新值,并且$s的最终值是系列中最后一次计算的表达式:

---Start
Dog:
Cat:
Bird:
---End
Dog: Snoopy
Cat: Garfield
Bird: Woody

s is Woody


这在Perl需要标量的某些地方很有用。考虑一个C风格的for循环,其中迭代单个变量,并且结构中的三个位置中的每一个都处理一个变量。任何这些地方都可能有副作用,但这是它通常的写法:

for( $i = 0; $i <= 137; $i++ ) { ... }


您还可以使用标量逗号在初始化和增量部分中产生多个副作用。这有时很有用,特别是当块可以跳过或调整参数时:

for( $i = 0, $j = 0; $i + $j <= 137; $i++, $j++ ) { ... }

答案建议

一个典型的答案使用示例表达式(1, 2, 3),因为这是一个自然的答案。然而,它带来了一个意想不到的混乱,因为无论哪种方式,它都评估为相同的东西,但原因不同:

my @array = ( 1, 2, 3 );
my $s = @array;   # size of array, 3


将该表达式赋值给标量也会得到3,因为这是系列中的最后一件事:

my $size = ( 1, 2, 3 );  # scalar comma


最好选择一个不同的例子,这样数字3就不会是偶然的结果。如果大小不是数组中的一个元素会更好,如果标量结果不是一个数字会更好。原来的问题是这样的:

('111','222','aaa','bbb');


然而,其他的答案都落入了这个陷阱。
一般来说,例如,选择非顺序或不相关的答案可以阐明机制。

xmakbtuz

xmakbtuz3#

当你把一个数组赋值给标量变量时,变量会被赋值一个数组的大小。值应为9。

@Array = (1,2,3,2,3,4,5,1,2);
$ScalarValue = @Array;
print("Scalar Variable should print, size of an array $ScalarValue);

字符串

相关问题