【问题标题】:Scalar vs list context in PerlPerl 中的标量与列表上下文
【发布时间】:2011-07-07 10:38:00
【问题描述】:

我在 O'Reilly 的书中发现一个例子有点奇怪:

@backwards = reverse qw/ yabba dabba doo /;
print "list context: @backwards\n";
$backward = reverse qw/ yabba dabba doo /;
print "scalar1 context: $backward\n";
$notbackward = qw/ yabba dabba doo /;
print "scalar2 context: $notbackward\n";
print "print context: ",reverse qw/ yabba dabba doo /;
print "\n";

输出是:

list context: doo dabba yabba
scalar1 context: oodabbadabbay
scalar2 context: doo
print context: doodabbayabba

我不明白的是scalar1 上下文:

这本书说'reverse something'给出了一个列表上下文,所以我猜qw/ yabba dabba doo /被视为一个列表,reverse qw/ yabba dabba doo /被视为('doo','dabba','yabba')。

$backward = something 也随之而来,这意味着某物是一个标量,所以我期待结果是 'doo dabba yabba',但它是不同的:'oodabbadabbay'。

我想,原因是不能直接将列表设置为标量。所以我做了scalar2 测试:只打印列表中的最新项目。为什么?为什么不在 scalar1 测试中?

标量测试输出如何工作?

【问题讨论】:

    标签: perl list scalar


    【解决方案1】:

    为了简化其他答案,reverse 实际上做了两件事,列表反转和字符串反转。

    这已被证明非常令人困惑,以至于 perl6 将它们拆分为不同命名的函数。

    【讨论】:

      【解决方案2】:

      所有 Perl 函数,包括您定义的任何 subcan detect whether they are being called in "scalar" or "list" context,并且有许多函数会根据此上下文更改其行为。

      除了 Do What I Mean 之外,关于函数何时以及如何以不同方式处理两种上下文的约定很少(whole thread on perlmonks 对这些问题有很好的讨论),因此您需要依赖每个函数猜测一个函数在特定上下文中会做什么。

      专门针对你的四个例子,

      1. @backwards = reverse qw/ yabba dabba doo /
      2. $backward = reverse qw/ yabba dabba doo /
      3. $notbackward = qw/ yabba dabba doo /;
      4. print ..., reverse qw/ yabba dabba doo /;
      

      行为是

      1. reverse function, list context:     returns list of the elements in reverse order
      
      2. reverse function, scalar context:   concatenate argument list to a string,
                                             return reverse of that string
      
      3. list assignment to scalar:          returns last element in list (*)
      
      4. also reverse function, list context    same as #1
      

      (*) - 注意列表赋值给标量不同于 array 赋值给标量 - 这是 listsarrays 之间最重要的区别之一

      @a = ("x", "y", "z");  $n = @a;   # array assignment,  $n is array size, or "3"
      $n = ("x", "y", "z");             # list assignment,   $n is last element, or "z"
      

      【讨论】:

        【解决方案3】:

        对于线路:

        $backward = reverse qw/ yabba dabba doo /;
        

        您正在从反向请求一个标量。反向的 perldoc 说:

        在标量上下文中,连接 LIST 的元素并返回一个字符串 包含所有字符的值 顺序相反。

        所以它返回每个颠倒的字母。

        对于 $notbackward = qw/ yabba dabba doo /; qw// 的 perldoc 说:

        评估为单词列表 从 STRING 中提取,使用 嵌入空格作为单词 分隔符。可以理解为 大致相当于:

                       split(’ ’, q/STRING/);
        

        不同之处在于它在 编译时间,在标量上下文中 返回列表中的最后一个元素。

        所以请求标量只返回列表中的最后一项。

        【讨论】:

          【解决方案4】:

          首先,qw/ yabba dabba doo / 只是('yabba', 'dabba', 'doo') 的语法糖。它们的意思是一样的。

          reverse 函数接受一个列表。在列表上下文中,它反转列表。在标量上下文中,它执行join('', @list),然后反转该字符串中的字符并返回它。

          记住

          $backward = reverse qw/ yabba dabba doo /;
          $notbackward = qw/ yabba dabba doo /;
          

          意思

          $backward = reverse ('yabba', 'dabba', 'doo');
          $notbackward = ('yabba', 'dabba', 'doo');
          

          reverse 函数提供列表上下文,$notbackward = 为我们提供标量上下文。这意味着逗号运算符位于第一行的列表上下文和第二行的标量上下文中。在列表上下文中,comma operator 创建一个列表。在标量上下文中,它计算两个操作数并返回右侧的操作数。这意味着在标量上下文中('yabba', 'dabba', 'doo') 的值是'doo',这就是分配给$notbackward 的值。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-26
            • 2012-03-07
            • 2014-09-24
            相关资源
            最近更新 更多