在语句中分配变量时,perl 中的三元运算符会产生意外结果

发布于 2024-11-13 02:40:57 字数 561 浏览 3 评论 0原文

我正在尝试从 php 过渡到 perl,预计会遇到一些奇怪的情况。我无法理解为什么我的代码的一个版本比另一个版本有效。

这失败了:

sub tester
{
$return;
($_[0] < 10) ? $return = "youre a youngin" : $return = "youre an old person";
return $return;
}


print "how old are you?";
$a = <>;
chomp $a;

print  tester($a);  #both result in "youre an old person"

但是这个有效:

sub tester
{
    return ($_[0] < 10) ? "youre a youngin" : "youre an old person";
}


print "how old are you?";
$a = <>;
chomp $a;
print  tester($a);

这里真正的区别是什么?!

I'm trying to make a transition from php to perl and expectedly running into some weirdness. I cannot understand why one version of my code works vs another.

This fails:

sub tester
{
$return;
($_[0] < 10) ? $return = "youre a youngin" : $return = "youre an old person";
return $return;
}


print "how old are you?";
$a = <>;
chomp $a;

print  tester($a);  #both result in "youre an old person"

however this one works:

sub tester
{
    return ($_[0] < 10) ? "youre a youngin" : "youre an old person";
}


print "how old are you?";
$a = <>;
chomp $a;
print  tester($a);

what is the real difference here?!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

围归者 2024-11-20 02:40:57

这和Perl的运算符优先级有关。在 Perl 中,

($_[0] < 10) ? $return = "youre a youngin" : $return = "youre an old fart";

相同

( ($_[0] < 10) ? $return = "youre a youngin" : $return ) = "youre an old fart";

与注意括号绑定到 FRONT

。这导致了 Perl 的另一个令人困惑的特性:条件左值:你可以这样做
(CONDITION ? $ASSIGN_A_IF_CONDITION_IS_TRUE : $ASSIGN_B_IF_CONDITION_IS_FALSE) = 2

这是一个修复

($_[0] < 10) ? ($return = "youre a youngin") : ($return = "youre an old fart");

http://codepad.org /MxBAy7wy

编辑:

但是,大多数人会写

$return = ($_[0] < 10) ? "youre a youngin" : "youre an old fart";

,从而节省了键入的冗余变量两次。

根据 Perl 和 PHP 文档,Perl ?: 是右关联的,而 PHP ?: 是左关联的。 (http://perldoc.perl.org/perlop.html)(http://php.net/manual/en/language.operators.precedence.php)

It is related to Perl's operator precedence. In Perl,

($_[0] < 10) ? $return = "youre a youngin" : $return = "youre an old fart";

is same as

( ($_[0] < 10) ? $return = "youre a youngin" : $return ) = "youre an old fart";

notice the paren binds to the FRONT.

and this leads to another confusing feature of Perl: conditional lvalues: You can do this
(CONDITION ? $ASSIGN_A_IF_CONDITION_IS_TRUE : $ASSIGN_B_IF_CONDITION_IS_FALSE) = 2

Here is a fix

($_[0] < 10) ? ($return = "youre a youngin") : ($return = "youre an old fart");

http://codepad.org/MxBAy7wy

EDIT:

However, most people would write

$return = ($_[0] < 10) ? "youre a youngin" : "youre an old fart";

, saving the redundancy of typing the variable twice.

According to Perl and PHP docs, Perl ?: is right-associative and PHP ?: is left-associative. (http://perldoc.perl.org/perlop.html ) (http://php.net/manual/en/language.operators.precedence.php )

如日中天 2024-11-20 02:40:57

啊,您已经发现为什么 ?: 是一个坏主意,除了在微不足道的情况下。

运算符优先级是问题所在。您很可能想要这样做:

$return = ($_[0] < 10) ? "you're a youngin'" : "you're an old fart";

不过,您的代码还存在一些其他问题。

  • 您应该声明您的变量。它们不像 PHP 那样在第一次使用时声明;您可以使用 my 运算符显式执行此操作。
  • 您应该始终、始终、始终在 Perl 代码中使用严格使用警告。这些编译指示禁用了古老的 Perl 恶作剧,并警告可能是错误的可疑操作。
  • 函数的第一行通常应该是解包 @_;没有什么理由直接在函数中使用 $_[0] 。 (这样做很危险,因为 @_ 是别名;您可以更改调用者的变量!)

因此您可能想要更像这样的东西:

use strict;
use warnings;

sub tester {
    my ($age) = @_;
    if ($age < 10) {
        return "you're a youngin'";
    }
    else {
        return "you're an old fart";
    }
}

print "how old are you? ";
my $age = <>;
chomp $age;

print tester($age);

请注意 my $x = ... 声明单个变量并分配单个值,而 my ($x, $y, $z) = ... 声明多个变量并将列表解包到其中。

my 变量称为词法变量,仅存在于声明它们的块中;它们不像 PHP 变量那样具有函数作用域。实际上,您可能应该在 perlsub

Ah, you've discovered why ?: is a bad idea except in trivial cases.

Operator precedence is the problem. You most likely want to do this:

$return = ($_[0] < 10) ? "you're a youngin'" : "you're an old fart";

There are a few other issues with your code, though.

  • You should declare your variables. They aren't declared on first use as in PHP; you do it explicitly with the my operator.
  • You should always, always, always use strict and use warnings in Perl code. These pragmas disable ancient Perl shenanigans and warn about suspicious operations that might be bugs.
  • The first line of a function should usually be unpacking @_; there's very little reason to use $_[0] directly in a function. (And it's dangerous to do so, since @_ is aliased; you could change the caller's variables!)

So you probably want something more like this:

use strict;
use warnings;

sub tester {
    my ($age) = @_;
    if ($age < 10) {
        return "you're a youngin'";
    }
    else {
        return "you're an old fart";
    }
}

print "how old are you? ";
my $age = <>;
chomp $age;

print tester($age);

Note that my $x = ... declares a single variable and assigns a single value, whereas my ($x, $y, $z) = ... declares multiple variables and unpacks a list into them.

my variables are called lexical and only exist within the block where you declare them; they aren't function-scoped like PHP variables. Actually you should probably just read about them in perlsub.

你曾走过我的故事 2024-11-20 02:40:57

这是一个优先事项。

($_[0] < 10) ? ($return = "youre a youngin") : ($return = "youre an old fart");

...效果更好。

但老实说,没有哪个认真的 Perl 程序员会这样写。首先,他们会将以下内容放在程序的顶部:

use warnings;
use strict;

其次,他们会将参数放入本地:

sub tester {
    my $arg = shift;

第三,他们会以两种方式之一编写条件:

if ($arg < 10) {
    $return = "you're a youngin";
}
else {
    $return = "you're an old fart";
}

如果他们来自 Lisp 背景,他们可能会放弃使用 $return 变量并编写:

return $arg < 10 ? "you're a youngin" : "you're an old fart";

It's a precedence thing.

($_[0] < 10) ? ($return = "youre a youngin") : ($return = "youre an old fart");

...works better.

But honestly, no serious Perl programmer would write it like this. First, they would put the following at the top of their program:

use warnings;
use strict;

Second, they would put the argument into a local:

sub tester {
    my $arg = shift;

Third, they would write the conditional in one of two ways:

if ($arg < 10) {
    $return = "you're a youngin";
}
else {
    $return = "you're an old fart";
}

If they came from a Lisp background, they would probably dispense with the $return variable and just write:

return $arg < 10 ? "you're a youngin" : "you're an old fart";
情丝乱 2024-11-20 02:40:57

如果你写:

sub tester
{
   return ($_[0] < 10) ? "You're a young'un" : "You're an oldie";
}

那么你就会得到你期望的结果。

If you write:

sub tester
{
   return ($_[0] < 10) ? "You're a young'un" : "You're an oldie";
}

then you get the result you expect.

甜味超标? 2024-11-20 02:40:57

基本上,运算符优先级。

Basically, operator precedence.

轻许诺言 2024-11-20 02:40:57

我相信 $return; 是一个语法错误。您不需要声明它 - perl 和 php 中的变量是无范围的。
此外,= 优先于 ?:,因此您需要将 () 添加到两个赋值中。

I believe $return; is a syntax error. You don't need to declare it - variables in perl and php are scopeless.
In addition = takes precedence over ?: so you need to add () to both assignments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文