Perl列表上下文使用defined-or操作符为何返回标量?
Perl 数组使用 defined-or(//)返回标量长度的原因说明
该行为不属于Perl的bug,是操作符的上下文传递规则和defined-or的设计特性共同导致的,具体原因如下:
- // 操作符强制左操作数为标量上下文
//、&&、||都属于短路双目操作符,这类操作符的左操作数永远会被强制在标量上下文求值。你向//左操作数传入数组@row时,Perl会先返回标量上下文下的数组长度值,整个@row // (10,20,30)的返回结果只有一个标量值,所以列表赋值时只有第一个变量$one能拿到数组长度,其余变量都是undef。 - 三元表达式的上下文传递规则不同
三元运算符COND ? EXPR1 : EXPR2的逻辑是:COND条件本身在标量上下文求值用来判断真假,但EXPR1和EXPR2会继承整个三元表达式所处的外层上下文。你写@row ? @row : (10,20,30)时,COND部分的@row确实是标量返回长度判断真假,但后续的@row和默认列表会在外层的列表上下文求值,正常展开为数组元素赋值。 defined(@array)报错而@array//不报错的原因
Perl 5.22及以上版本直接禁用了defined()对数组、哈希这类聚合类型的直接调用,所以显式写defined(@row)会直接抛出语法错误。但@row // ...的逻辑是先将左操作数@row转成标量(长度值,是数字类型的标量),再对这个标量做defined判断,因此不会触发语法错误。
额外注意:空数组在标量上下文返回的0是合法的defined值,所以不管数组是否为空,
@array // 默认值的写法永远不会触发默认值,完全达不到 fallback 效果。
正确的数组列表默认值写法
直接使用测试中可用的三元表达式即可:
# 数组非空时用数组元素,空时用默认列表 ($one, $two, $three) = @row ? @row : (10,20,30);
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

