18

スカラー (ブール値) コンテキストで式を評価するとき、Perl は1、式が true と評価される場合は結果として明示的な値を使用し、式が false と評価される場合は空の文字列を使用します。0Perl がブール値の false 値を表すために空の文字列を使用し、どちらがより直感的ではないのか、私は興味があります。

Perl が空の文字列をスカラー (ブール) コンテキストで false として扱うことには関心がないことに注意してください。

編集

"false"true の文字列 (たとえば) を false 値の文字列表現として使用すると、既存のコードの意味がどのように変わるでしょうか? そのような変更の後にセマンティクスを変更するコードは、以前よりも堅牢性/正確性が低下していると言えますか? 文字列コンテキストは Perl で非常に普及しているため、正しいセマンティクスにつながる唯一のオプションは、ブール値が文字列との間のラウンドトリップ後にその値を保持する場合です...

4

5 に答える 5

32

さまざまな論理演算子は空の文字列を返すのではなく、3 つの単純なスカラー型すべてで false または true の値を返します。print引数に文字列コンテキストを強制するため、空の文字列を返すように見えます。

#!/usr/bin/perl

use strict;
use warnings;

use Devel::Peek;

my $t = 5 > 4;
my $f = 5 < 4;

Dump $t;
Dump $f;

出力:

SV = PVNV(0x100802c20) at 0x100827348
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 1
  NV = 1
  PV = 0x100201e60 "1"\0
  CUR = 1
  LEN = 16
SV = PVNV(0x100802c40) at 0x100827360
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x100208ca0 ""\0
  CUR = 0
  LEN = 16

Perl 5 の内部構造に慣れていない方のために説明すると、 aPVNVは 3 つの単純なスカラー型 (integer IV、倍精度 float NV、string PV) をすべて保持するスカラー構造体です。フラグIOKNOK、およびPOKは、integer、double、および string の値がすべて同期していることを意味するため (同期の定義によって)、それらのいずれかを使用できます (つまり、整数として使用する場合は変換を行う必要はありません)。 、double、または文字列)。

空の文字列が偽の文字列として選択されたの"0". 小さいという私の声明は無視してください。両方とも""同じ"1"サイズです: 16 文字です。ダンプでそう言っています。Perl 5 では、文字列が急速に大きくなるように、文字列に余分なスペースを追加します。

ああ、私はあなたが嫌い​​です。これを調査したところ、嘘をついたことperlopquickがわかり、修正する方法を見つける必要があります。あなたが他のすべての羊と同じように、Perl 5 の表面の奇妙さを事実として受け入れていれば、私がやるべきことはもっと少なくなったでしょう。

編集セクションの質問への回答:

false 値の文字列表現として true (たとえば "false") の文字列を使用すると、既存のコードの意味がどのように変わるでしょうか?

PL_sv_yes と PL_sv_no (比較演算子によって返される正規の true 値と false 値) に関する唯一の特別な点は、それらが読み取り専用であり、perl実行中のプログラムによって作成されないことです。これらを変更しても真偽判定は変わらないため、PL_sv_no を設定する"false"と true として扱われます。ドキュメント化されていない次の機能を使用して、自分でこれを行うこともできます (このコードは、Perl 5.18 と最新の Perl の間のある時点で機能しなくなります) perl

#!/usr/bin/perl

use strict;
use warnings;
use Scalar::Util qw/dualvar/;

BEGIN {
        # use the undocumented SvREADONLY function from Internals to
        # modify a reference to PL_sv_no's readonly flag
        # note the use of & to make the compiler not use SvREADONLY's
        # prototype, yet another reason prototypes are bad and shouldn't
        # be used
        &Internals::SvREADONLY(\!!0, 0);

        # set PL_sv_no to a dualvar containing 0 and "false"
        ${\!!0} = dualvar 0, "false";
}

if (5 < 4) {
        print "oops\n";
}

出力

opps

これは、真実性テストが最初に文字列を調べるためです。

そのような変更の後にセマンティクスを変更するコードは、以前よりも堅牢性/正確性が低下していると言えますか?

真っ直ぐ壊れます。int 0 または文字列 "0" (どちらも false) に設定するように制限しても、一部の有効なコードが壊れます。

文字列コンテキストは Perl で非常に普及しているため、正気のセマンティクスにつながる唯一のオプションは、ブール値が文字列との間のラウンドトリップ後にその値を保持する場合です...

はい。

于 2010-10-12T12:09:35.303 に答える
5

次のように、true、false、および undef の文字列化をオーバーロードできます

&Internals::SvREADONLY( \ !!1, 0);    # make !!1 writable
${ \ !!1 } = 'true';                  # change the string value of true
&Internals::SvREADONLY( \ !!1, 1);    # make !!1 readonly again
print 42 == (6*7);                    # prints 'true'

&Internals::SvREADONLY( \ !!0, 0);    # make !!0 writable
${ \ !!0 } = 'false';                 # change the string value of false
&Internals::SvREADONLY( \ !!0, 1);    # make !!0 readonly again
print 42 == (6*6);                    # prints 'false'
于 2010-10-12T16:58:50.087 に答える
2

Perl では、数値 0 と空の文字列の両方が最終的に false と評価されます。これは言語設計の問題だと思います。独自のコードを作成するときは、もちろん、誤ったエンコーディング規則を想定することができます。

詳細については、" How do I use boolean variables in Perl? " を参照してください。

于 2010-10-12T11:33:50.257 に答える
2

それが Perl で間違っているだけ ""ではありません。理由については... Perlが素晴らしいかひどいかのどちらかです-個人的な好みに応じて:)

于 2010-10-12T11:31:36.683 に答える
1

これが私が問題を回避した方法です:

my $res = ($a eq $b) *1;

*1、結果のブール値($a eq $b)をスカラーに変換します。

于 2014-12-03T16:45:15.617 に答える