Perl 定义或在列表上下文中,为什么是标量?

Jan*_*Jan 5 perl

use strict;
use warnings;
use Test::More;

subtest 'explicit array' => sub  {
    my @row = (1,2,3);
    # let's disassamble the array.
    # without default it works:
    my ($one, $two, $three) =  @row;
    is($one, 1, 'one');
    # this works too:
    ($one, $two, $three) =  @row ? @row : (10,20,30);
    is($one, 1, 'one');
    # and the default hits
    my @emptyness;
    ($one, $two, $three) = @emptyness ? @emptyness : (10,20,30);
    is($one, 10, 'one default');
    # however, this squashes the array to a scalar
    ($one, $two, $three) =  @row // (10,20,30);
    is($one, 3, 'scalar, length');
    is($two, undef, 'nothing else');
    # shouldn't 'defined-or' be equivalent to a ternary with a check against undef?
    # ($one, $two, $three) = defined @emptyness ? @emptyness : (10,20,30); # fails!
    # "Can't use 'defined(@array)' (Maybe you should just omit the defined()?)"
    # Probably @array // ... should fail in the same way, but instead it returns @array
    # in a scalar context.
    # so maybe this is a bug
};


done_testing();
Run Code Online (Sandbox Code Playgroud)

或者有人可以给我这种行为的合理解释吗?

Dad*_*ada 5

您所观察到的行为是预期的行为。这记录在perlop 的Logical Defined-Or部分中:

EXPR1 // EXPR2如果定义则返回 的值,否则返回EXPR1的值。EXPR2(在标量上下文中,在 // 本身的上下文中EXPR1计算)。EXPR2

并且,perldoc 后来提供了以下示例:

特别是,这意味着您不应该使用它来在两个聚合之间进行选择以进行分配:

@a = @b || @c;            # This doesn't do the right thing
@a = scalar(@b) || @c;    # because it really means this.
@a = @b ? @b : @c;        # This works fine, though.
Run Code Online (Sandbox Code Playgroud)