【问题标题】:What is the difference between the scalar and list contexts in Perl?Perl 中的标量上下文和列表上下文有什么区别?
【发布时间】:2010-09-27 11:25:05
【问题描述】:

Perl 中的标量和列表上下文有什么区别?这在其他语言(如 Java 或 Javascript)中是否有任何相似之处?

【问题讨论】:

    标签: perl list scalar


    【解决方案1】:

    这仅仅意味着数据类型将根据操作模式进行评估。例如,对标量的赋值意味着右侧将被评估为标量。

    我认为理解上下文的最好方法是学习wantarray。所以想象一下=是一个实现wantarray的子​​程序:

    sub = {
      return if ( ! defined wantarray ); # void: just return (doesn't make sense for =)
      return @_ if ( wantarray ); # list: return the array
      return $#_ + 1; # scalar: return the count of the @_
    }
    

    this post 中的示例就像通过将右侧作为参数传递来调用上述子例程一样。

    至于其他语言的相似之处,是的,我仍然认为几乎每种语言都支持类似的东西。多态性在所有 OO 语言中都是相似的。另一个例子,Java 在某些上下文中将对象转换为字符串。而且我用过的每一种无类型脚本语言都有类似的概念。

    【讨论】:

    • 问题是关于标量/列表上下文而不是标量/数组变量。这个概念是 Perl 独有的 AFAIK。
    • 是的,我误解了这个问题。已编辑。
    • 更好。如果可以的话,我会取消投票,但 SO 告诉我它“太旧了”。
    【解决方案2】:

    Perl 中的各种运算符都是上下文相关的,并在列表和标量上下文中产生不同的结果。

    例如:

    my(@array) = (1, 2, 4, 8, 16);
    my($first) = @array;
    my(@copy1) = @array;
    my @copy2  = @array;
    my $count  = @array;
    
    print "array: @array\n";
    print "first: $first\n";
    print "copy1: @copy1\n";
    print "copy2: @copy2\n";
    print "count: $count\n";
    

    输出:

    array: 1 2 4 8 16
    first: 1
    copy1: 1 2 4 8 16
    copy2: 1 2 4 8 16
    count: 5
    

    现在:

    • $first 包含 1(数组的第一个元素),因为 my($first) 中的括号提供了数组上下文,但 $first 中只有一个值的空间。
    • @copy1@copy2 都包含@array 的副本,
    • 并且$count 包含 5,因为它是一个标量上下文,而@array 计算为标量上下文中数组中的元素数。

    还可以构建更详细的示例(结果仅供读者练习):

    my($item1, $item2, @rest) = @array;
    my(@copy3, @copy4) = @array, @array;
    

    在我所知道的其他语言中,列表和标量上下文没有直接的平行关系。

    【讨论】:

    • 谢谢。我喜欢你的例子,除了一个小问题:如果你用 1,2,3 以外的值填充你的数组,那么 $copy2 的值​​将是 3 以外的其他数字,它不会与大小混淆数组本身。起初我很困惑。但你解释了。 np.
    • 我认为如果将 $count 更改为 $copy1,将 @copy1 更改为 @copy2 并将 $copy2 更改为 $count,会更清楚。然后变量名称将匹配内容。
    • 变量命名还有很多不足之处。我会返工: $count -> $first; $copy1 -> $acopy; $copy2 -> $count.
    【解决方案3】:

    标量上下文是您在寻找单个值时得到的。列表上下文是您在寻找多个值时得到的。最常见的区别之一是使用数组时:

    @x = @array;  # copy an array
    $x = @array;  # get the number of elements in an array
    

    其他运算符和函数也是上下文相关的:

    $x   = 'abc' =~ /(\w+)/;  # $x = 1
    ($x) = 'abc' =~ /(\w+)/;  # $x = 'abc'
    @x   = localtime();       # (seconds, minutes, hours...)
    $x   = localtime();       # 'Thu Dec 18 10:02:17 2008'
    

    运算符(或函数)在给定上下文中的行为取决于运算符。对于事物的行为方式没有一般规则。

    您可以使用wantarray 函数确定调用上下文,使您自己的子例程上下文敏感。您可以使用 scalar 关键字强制在标量上下文中计算表达式。

    除了标量和列表上下文,您还会看到文档中提到的“void”(不期望返回值)和“boolean”(期望的真/假值)上下文。

    【讨论】:

    • 我喜欢您的“其他运算符”示例,尤其是 =~ 运算符在标量和列表上下文中的显着行为。我不会猜到这种行为。
    • 是的,在标量上下文中 =~ 告诉您某些内容是否匹配。在列表上下文中,它返回一个包含捕获文本的列表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 2020-10-29
    • 2017-10-07
    • 2021-12-26
    • 2021-03-10
    • 1970-01-01
    • 2012-01-01
    相关资源
    最近更新 更多