【问题标题】:Assigning using ternary operator?使用三元运算符赋值?
【发布时间】:2012-02-14 12:34:26
【问题描述】:

我在 Perl 5.8 上,需要分配一个默认值。我最终这样做了:

if ($model->test) {
    $review = "1"
} else {
    $review = ''
}

$model->test 的值将是 "1" 或未定义。如果$model->test 中有内容,则将$review 设置为"1",否则将其设置为等于''

因为它不是 Perl 5.10,所以我不能使用新的时髦的定义或运算符。我的第一反应是像这样使用三元运算符...

defined($model->test) ? $review = "1" : $review = '';

但这也没用。

有没有人知道如何更有效地分配这个? 珍妮

【问题讨论】:

  • 你真的应该把它设置为!1而不是''。它们都具有相同的字符串表示形式 ('')。唯一的区别是'' 会在您尝试将其用作数字时发出警告,而!1 不会。 (假设你总是在每段 Perl 代码的顶部有use warnings;,就像你应该的那样。)

标签: perl variables ternary-operator


【解决方案1】:

我通常会这样写:

$review = ( defined($model->test) ? 1 : '' );

括号是为了让其他阅读代码的人更清楚。

【讨论】:

  • 谢谢格雷格!我什至觉得很奇怪,因为它似乎就是这么简单。 (确实如此!)JW
  • @JaneWilkie 实际上,甚至比这更容易。看我的回答。
  • 当然更好的方法是将 MySQL 的定义更改为 CHAR(1) 而不是 BIT(1),但遗憾的是,在我们的生产环境中更改如此简单的东西的政治意义是巨大的。跨度>
  • @Greg 在我看来,多余的括号只会损害可读性。
  • 此答案中不需要defined。另外,如果该方法开始返回 ''0 而不是 undef,它可能会导致代码在未来中断。
【解决方案2】:

$model->test 将是 "1" 或未定义。如果$model->test中有东西,则将$review设置为"1",否则设置为''

那就用这个吧:

$review = $model->test || "";

【讨论】:

  • Tom 和 Foy 在同一个线程中。拉里沃尔在哪里?我希望我们都排好队,这样我就可以和你们合影了。
【解决方案3】:

首先,“这也不起作用”不是您能告诉我们的最有用的话。准确了解它如何不起作用很重要:它做了什么,您期望什么,以及它们有何不同?

但是问题

defined($model->test) ? $review="1" : $review='';

是运算符优先级。条件运算符? :比赋值运算符=绑定得更紧密,所以上面等价于:

(defined($model->test) ? $review="1" : $review) = '';

所以如果定义了$model->test,它就相当于

$review = "1" = '';

你可以用括号解决这个问题:

defined($model->test) ? ($review="1") : ($review='');

但实际上,你为什么要这样做?当您想要使用结果时,条件(三元)运算符很有用。如果结果将被丢弃,就像这里一样,使用 if/else 语句会更清楚(并且,正如您所见,更不容易出错):

if (defined($model->test) {
    $review = "1";
}
else {
    $review = "";
}

或者,如果你坚持写在一行:

if (defined($model->test) { $review = "1"; } else { $review = ""; }

如果你真的想使用条件表达式,你可以这样做:

$review = defined($model->test) ? "1" : "";

这可能是一种合理的方式。

但是:

defined 运算符本身产生"1" (true) 或"" (false)。所以整个事情可以简化为:

$review = defined($model->test);

【讨论】:

  • 如果undef 只是一个假值,并且方法被重写以返回''0 作为一个假值怎么办?
  • @BradGilbert:那么我想你不会想对它应用defined。您显然需要知道该方法返回什么才能使用它。
  • 提供适合其他所有用途的值不是 test() 的工作,依赖它是一种糟糕的形式。这类东西会导致紧密耦合和硬测试。
【解决方案4】:

你有一个优先级问题。你所拥有的是一样的

( defined($model->test) ? $review="1" : $review ) = '';

你可以让它与括号一起工作。

my $review; defined($model->test) ? ( $review='1' ) : ( $review='' );

但是将作业移出要干净得多。

my $review = defined($model->test) ? '1' : '';

继续前进,检查值是否已定义毫无意义。看到仅有的两个可能值是undef 和字符串1,一个简单的真值测试就可以了。

my $review = $model->test ? '1' : '';

事实上,既然你希望真值不变,你可以简单地使用以下

my $review = $model->test || '';

最后,您真的需要将undef 更改为空字符串吗?如果没有,您可以简单地使用以下内容:

my $review = $model->test;

【讨论】:

  • 想一想我想知道:鉴于a ? b : cbc 评估取决于a,或者都评估到一些临时寄存器,并且正在使用的值取决于a?当bc 有副作用时(如问题所示),这会产生很大的不同。我认为大多数用户希望只有一个bc 被评估。
  • @U. Windl,(这作为一个问题会更好。)它使用short-circuit evaluation,这意味着它只评估必要的内容。对于E1 || E2E1 or E2E1 && E2E1 and E2 也是如此,这就是为什么我们可以做到open(...) or die(...)
【解决方案5】:
my $result = defined $model->test ? '1' : '';

【讨论】:

  • 这会将$result 设置为与$result = defined $model->test; 几乎相同的值。主要区别在于,如果用作数字,您的会发出警告。
【解决方案6】:

我假设$model->test 应该返回一个真或假值。

除非它特别声明错误值为undef,否则可以重写该方法以开始返回一些其他错误值。 这会破坏仅检查值是否已定义的任何内容。
(我认为该方法返回 undef 而不是规范的 false 值是一个错误。)

所以设置$review最好的方法是测试返回值的真实性;不是定义。

my $review = $model->test ? 1 : '';

我想指出,这仍然有一个错误。 如果您希望能够将该值用作数字,如果它为 false,它将发出警告。

要解决这个问题,您应该返回 !1(规范的 false 值),这将返回一个值,即字符串 '',但数值也为 0。

my $review = $model->test ? 1 : !1;

请注意,它可以简化为:

my $review = !! $model->test; # invert it twice

如果您只想在值为 false 时更改该值,则可以使用 or 运算符||

my $review = $model->test || !1;

如果您真的只想知道它是否已定义,为什么不直接使用defined

my $review = defined $model->test;

如果您只想在未定义时更改该值,并且您拥有 Perl 5.10 或更高版本,则可以使用defined-or operator (//)

my $review = $model->test // !1;

在较旧的 Perl 上,这将需要多个 statement

my $review = $model->test;
$review = !1 unless defined $review;

【讨论】:

  • 我喜欢这种情况下的双重反转。无论 $model 实际返回什么,它都能确保一个布尔值。简洁而清晰的 IMO。
【解决方案7】:

除了条件运算符,我经常喜欢使用do,它返回最后一个计算表达式的值:

my $review = do {
     if( ... ) { 'foo' }
  elsif( ... ) { 'bar' }
  elsif( ... ) { 'baz' }
  else         { 'defaut' }
  };

【讨论】:

  • 在这种情况下有点矫枉过正。不过,在您的工具箱中添加另一种技术总是值得的,谢谢。
猜你喜欢
  • 2013-06-28
  • 1970-01-01
  • 2011-07-02
  • 2021-04-29
  • 2021-11-23
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
相关资源
最近更新 更多