【问题标题】:Context of Scalar,List,Void [closed]标量,列表,无效的上下文[关闭]
【发布时间】:2014-01-03 11:39:33
【问题描述】:

我是 Perl 初学者。我不明白为什么我们在 perl 中使用 context(scalar,list,void)

请用简单的例子澄清我的疑问。

【问题讨论】:

  • 为您的问题提供一些上下文,在哪里使用?
  • @nrathaus 我已经提到了beginner。我不关心Context。用perl语言举个简单的例子
  • 这个问题可能因为几个原因而被关闭为题外话,包括@nrathaus 提到的缺乏特异性。我决定回答是因为它是 Perl 的一个绝对必要且经常被误解的特性。它应该对初学者有用。

标签: perl user-defined-functions


【解决方案1】:

带数组的简单示例

数组是列表上下文中包含的值的列表,而标量上下文中包含的值的数量。在 void 上下文中,它的值被丢弃。

$, = ' '; # printed fields will be delimited by spaces
my @arr = qw/a b c d/;
@arr; # nothing done (thrown away) in void context
print @arr, "\n"; # function arguments are evaluated in list context by default
print scalar(@arr), "\n"; # scalar() forces scalar context

“默认”指的是子程序原型。请参阅perlsub 手册页 (man perlsub)。

输出:

a b c d
4

空上下文示例及说明

IMO 的空上下文并不是很有趣。它正在丢弃价值。如果您调用返回值的子例程而不捕获该值(例如在变量中),它将在 void 上下文中调用。 请注意,隐式返回看起来不像捕获值,但在这种情况下,上下文是从调用者继承的。

sub x {
    return 42;
}
x(); # evaluated in void context

有趣的是,即使子程序返回了一些东西,这也不会产生错误。只有在启用警告时,在 void 上下文中使用常量或变量才会产生警告。

子程序内的上下文

在子程序中,调用者的上下文可以使用wantarray 来确定。对于 void 上下文,它返回 undef,对于列表上下文返回 true,对于标量上下文返回 false。 return 参数中的表达式在此上下文中计算。

sub print_context {
    my $context = wantarray;
    unless (defined $context) {
        print "void\n";
    } elsif ($context) {
        print "list\n";
    } else {
        print "scalar\n";
    }
    return ''; # empty string
}
print_context(); # void
scalar(print_context()); # scalar
(print_context()); # void
print print_context(); # list
print (print_context()); # list
print +(print_context(), print_context()); # list twice
print scalar(print_context(), print_context()); # void, scalar (comma operator throws away its left operand’s value)
print scalar(+(print_context(), print_context())); # void, scalar (same as above)
print scalar(@{[print_context(), print_context()]}); # list twice, 2 once (array of two empty strings)

我必须承认scalar(print_context()); 让我感到惊讶。我预计无效。

可以找到越来越复杂的人工例子。

与上下文相关的实际问题

了解上下文的需要来自几个实际问题:

  • 通过强制标量上下文确定数组大小(通常通过scalar() 或使用期望标量的运算符之一)
  • 解决了在标量上下文中错误地评估数组(因此扩展到其大小)而不是通过强制列表上下文来解决的事故
  • 使用在不同上下文中行为不同的运算符和子例程(例如=~,<> aka readlinelocaltimereverseeachcaller、...;和那些使用wantarray 的用户定义,自然)

关于上下文的一般和非常深刻的真相

  • perldata 手册页 (man perldata) 中解释了上下文的概念。
  • 赋值运算符 (=) 的左操作数决定了右操作数的计算上下文。赋值运算符的行为取决于左操作数的类型。
  • 上述子例程原型包括评估其参数的上下文。请参阅 perlsub 手册页 (man perlsub)。
  • return’s 参数中的表达式在从调用者继承的上下文中进行评估。
  • Parentheses have nothing to do with context,甚至没有列表上下文和列表。他们总是在改变优先级。 或者它们围绕函数调用参数列表,形成一个术语。请参阅 perlop 手册页 (man perlop)。

【讨论】:

  • 我正在等待编辑答案..请完成
  • 我试过你的答案my @arr = qw/a b c d/; print @arr, "\n"; print scalar(@arr), "\n"; 它给出的输出类似于abcd 4。为什么它显示的字母之间没有空格?
  • @user3098497 抱歉,忘记提及$,(输出字段分隔符)的使用。见man perlvar。再次编辑。
  • 使用join()函数我们可以减少这个
  • @user3098497 使用 join 后,这两行将比在评估 @arr 的上下文中有所不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 2011-07-07
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多