web-dev-qa-db-ja.com

三項演算子を使用して割り当てますか?

私は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 = '';

しかし、それもうまくいきませんでした。

これをより効率的に割り当てる方法を知っている人はいますか?ジャニー

26
Jane WIlkie

私は通常これを次のように書きます:

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

ここで、括弧は、コードを読む他の人々のために明確にするためのものです。

37
Greg D'Arcy

優先順位の問題があります。あなたが持っているものは同じです

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

あなたはそれを括弧で動作させることができます。

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

しかし、割り当てを移動する方がずっとクリーンです。

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

もちろん、あなたは単に使うことができます

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

しかし、なぜundefを空の文字列に変更するのですか?

my $review = $model->test;
20
ikegami

$model->testは、"1"または未定義のいずれかになります。 $model->testに何かがある場合は、$review"1"に設定します。それ以外の場合は''に設定します

次に、これを使用します:

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

条件演算子に加えて、最後に評価された式から値を返すdoを使用することがよくあります。

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

まず、「それでもうまくいかなかった」というのは、私たちに伝えることができる最も役立つ情報ではありません。 それがうまくいかなかった方法を正確に知ることは重要です:それは何をしましたか、あなたは何を期待しましたか、そしてそれらはどのように違うのですか?

しかし、問題

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

演算子の優先順位です。条件演算子? :は、代入演算子よりも強く結合します=なので、上記は次と同等です。

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

したがって、$model->testが定義されています。これは

$review = "1" = '';

あなたは括弧でその問題を修正することができます:

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

しかし、本当に、なぜあなたはそうしたいのでしょうか?条件付き(3項)演算子は、結果を使用する場合に役立ちます。ここにあるように、結果が破棄される場合は、if/elseステートメントを使用する方が明確です(見たとおり、エラーが発生しにくくなります)。

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

または、1行で記述すると主張した場合:

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

本当に条件式を使いたいなら、これを行うことができます:

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

これはおそらくそれを行うための合理的な方法です。

しかし:

defined演算子自体は"1"(true)または""(false)。したがって、全体を次のように減らすことができます。

$review = defined($model->test);
2
Keith Thompson

$model->testはtrueまたはfalseの値を返すことになっていると思います。

False値がundefであると明記されていない限り、メソッドは、代わりに他のいくつかのfalse値を返すように書き直すことができます。これは、値が定義されているかどうかをチェックするだけで壊れるものです。
(メソッドが正規のfalse値ではなくundefを返すのはバグだと思います。)

したがって、$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演算子(// を使用できます。

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

古いPerlでは、複数の statement が必要になります。

my $review = $model->test;
$review = !1 unless defined $review;
2
Brad Gilbert
my $result = defined $model->test ? '1' : '';
1
zgpmax