7

私はここに新しいです。質問方法と形式を読んだ後、これが問題ない質問になることを願っています. 私は perl にあまり熟練していませんが、私が最もよく知っているプログラミング言語です。

私は Perl を実生活に適用しようとしましたが、特に妻からはよく理解できませんでした。私は彼女にこう言います:

彼女が夕方にビールを3本持ってきてくれなかったら、それは私がビールを0 杯 (またはまったく飲まなかった)ことを意味します。

ご想像のとおり、あまり成功していません。:(

今、実際に。perlopから:

単項「!」論理否定、つまり「not」を実行します。

言語、boolean型を持つもの (2 つの「値」のみを持つことができるもの) は問題ありません。

それが 1 つの値でない場合 ->別の値でなければなりません

とても自然に:

!true  -> false
!false -> true

しかし、perl には変数がbooleanありませtruth systemん。数値などの非論理値に論理否定を適用すると、問題が発生します。0'0' undef''

たとえば、ある数値が3でない場合、実際の意味ではなく、それがゼロまたは空であることを意味します。3 でない場合、3 以外の値を意味します(:ゼロも)。

次のコードは次のとおりです。

use 5.014;
use Strictures;

my $not_3beers = !3;

say defined($not_3beers) ? "defined, value>$not_3beers<" : "undefined";
say $not_3beers ? "TRUE" : "FALSE";

my $not_4beers = !4;
printf qq{What is not 3 nor 4 mean: They're same value: %d!\n}, $not_3beers if( $not_3beers == $not_4beers );
say qq(What is not 3 nor 4 mean: @{[ $not_3beers ? "some bears" : "no bears" ]}!) if( $not_3beers eq $not_4beers );

say ' $not_3beers>',  $not_3beers, "<";
say '-$not_3beers>', -$not_3beers, "<";
say '+$not_3beers>', -$not_3beers, "<";

プリント:

defined, value><
FALSE
What is not 3 nor 4 mean: They're same value: 0!
What is not 3 nor 4 mean: no bears!
 $not_3beers><
-$not_3beers>0<
+$not_3beers>0<

さらに:

perl -E 'say !!4'

4 でないものは、4 の代わりに1です!

上記の妻に関する記述は「偽」(0 を意味する) :) ですが、実際に息子に Perl を教えようとすると、息子はしばらくして妻に尋ねました: 3 でないものが 0 を意味するのはなぜですか? .

質問は次のとおりです。

  • これを息子にどう説明するか
  • なぜperlはこのデザインを持っているので、なぜ!0毎回1なのか
  • ここでは、乱数で!0はなく0よりも「背後にある」何かが必要です。
  • すでに言ったように、私は他の言語をよく知りません - すべての言語で!3 == 0?
4

4 に答える 4

12

あなたは否定に重点を置いており、Perl のブール値が何を意味するかについてはあまり注目していないと思います。

歴史/実装の観点

真実とは?xボルトより高い電圧の検出。

より高い抽象化レベル: このビットが設定されている場合。

ビット シーケンスの抽象化は、整数と見なすことができます。この整数は偽ですか? はい、ビットが設定されていない場合、つまり整数がゼロの場合。

ハードウェア指向の言語は、C などのこの真実の定義を使用する可能性が高く、Perl を含むすべての C の子孫です。

の否定は、ビットごとの0否定 (すべてのビットが反転される) である可能性があります。1または、最後のビットを に設定するだけ1です。-1通常、結果はそれぞれ整数およびとしてデコードされます1が、後者の方がエネルギー効率が高くなります。

実用的な視点

カウントを扱うとき、ゼロ以外のすべての数をと考えると便利です。

my $wordcount = ...;

if ($wordcount) {
  say "We found $wordcount words";
} else {
  say "There were no words";
}

また

say "The array is empty" unless @array;  # notice scalar context

Perl のような実用的な言語は、ゼロを false と見なす可能性があります。

数学的観点

数値が偽である理由はありません。すべての数値は明確に定義されたエンティティです。真か偽かは、真か偽かの述語、つまり式によってのみ明らかになります。この真理値のみ否定できます。例えば

¬(x ≤ y) where x = 2, y = 3

は偽です。数学の基礎がしっかりしている多くの言語は、偽は何も考慮せず、特別な偽の値と見なします。Lips では'()ornilは通常は false ですが、0通常は true になります。つまり、値が nil でない場合にのみ true になります!

そのような数学言語で!3 == 0は、型エラーである可能性があります。

Re:ビール

ビールはおいしいです。ビールが 1 つあれば、何杯飲んでもかまいません。

my $beers = ...;

if (not $beers) {
  say "Another one!";
} else {
  say "Aaah, this is good.";
}

ビールをカウントする変数のブーリフィケーションは、ビールがあるかどうかを示します。!!ブール化演算子であると考えてください:

my $enough_beer = !! $beers;

ブール化は、正確な量には関係ありません。しかし、おそらく3以上の任意の数が良いでしょう。それで:

my $enough_beer = ($beers >= 3);

否定は十分なビールではありません:

my $not_enough_beer = not($beers >= 3);

また

my $not_enough_beer = not $beers;

fetch_beer() if $not_enough_beer;

セット

Perl のスカラーは、宇宙全体を象徴するものではありません。特に、not 33 つでないすべてのエンティティのセットではありません。式3は真の値ですか? はい。したがって、not 3偽の値です。

真であるという提案された動作は4 == not 3、おそらく望ましくないでしょう。4「3 でないすべてのもの」は等しくなく、4 は 3 でない多くのものの 1 つにすぎません。正しく書く必要があります。

4 != 3    # four is not equal to three

また

not( 4 == 3 )   # the same

!andnot論理否定と考えると役立つかもしれませんが、exceptとは異なります。

教え方

数学的な述語、つまり true または false になる式を導入する価値があるかもしれません。たとえば、明示的なテストによって真実性を「作成」するだけであればlength($str) > 0、問題は発生しません。結果に名前を付けることができますmy $predicate = (1 < 2): これにより、 trueまたはfalseprint $predicate ? "True" : "False"の特別な表現を考慮する問題が回避されます。

foo if $x値が true/false であると直接見なすことは、ショートカットにすぎません。たとえば、

foo if defined $x and length($x) > 0 and $x != 0;

Perl はショートカットがすべてです。

これらのショートカット、および perl のさまざまなコンテキストと、それらが現れる場所 (数値/文字列/ブール演算子) を教えることは役に立ちます。

  • リスト コンテキスト
    • 偶数サイズのリスト コンテキスト
  • スカラー コンテキスト
    • 数値コンテキスト
    • 文字列コンテキスト
    • ブール コンテキスト
  • 無効なコンテキスト
于 2013-07-05T15:30:33.770 に答える
8
  • すでに言ったように、私は他の言語をよく知りません - すべての言語で !3 == 0?
  • はい。C (および C++) でも同じです。

    void main() {
        int i = 3;
        int n = !i;
        int nn = !n;
        printf("!3=%i ; !!3=%i\n", n, nn);
    }
    

    プリント ( http://codepad.org/vOkOWcbUを参照)

    !3=0 ; !!3=1
    

  • これを息子にどう説明するか
  • とてもシンプルです。「もちろんfalseである、false以外の値の反対!3」を意味します。これは「コンテキスト」と呼ばれます。否定演算子によって課されるブールコンテキストでは、「3」は数値ではなく、真/偽のステートメントです。

    結果も「ゼロ」ではなく、false の便利な Perl 表現です。これは、数値コンテキストで使用するとゼロになります (ただし、文字列コンテキストで使用すると空の文字列になります。 と の違いを参照してください0 + !3) !3 . "a"

    Boolean コンテキストは、文字列や数値への変換が実行されない特別な種類のスカラー コンテキストです。( perldoc perldata)


  • なぜ perl はこのような設計になっているのか、なぜ !0 は毎回 1 なのか
  • 上記を参照。他にも考えられる理由がありますが (それが Larry の主な理由かどうかはわかりませんが)、C にも同じロジックがあり、Perl は構文やアイデアの多くを C から取り入れています。

    非常に優れた基礎となる技術的な詳細については、次の回答を参照してください: "ブール値を返すPerl関数は実際に何を返しますか?


  • !0 が乱数ではなく 0 であるよりも必要な「背後」にあるものはここにあります。
  • 実装の単純さ以外には何もありません。乱数よりも「1」を生成する方が簡単です。

  • 「0 を取得するために否定された元の # ではなく 1 である理由」というの質問をしている場合、その答えは簡単です。ゼロ/偽の値をもたらす他の式とは対照的に、ゼロは "!3" の結果であることを覚えています。

于 2013-07-05T14:32:19.080 に答える
0

偽の値を論理的に否定するには、結果の真の値を表すために何らかの値を選択する必要があります。"1" は、どの選択肢よりも優れた選択肢です。どの値が返されるかは重要ではありません (逆に、返される特定の真の値に依存しないことが重要です)。

于 2013-07-05T14:21:38.913 に答える