パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

「配列のすべての要素が条件を満たすならtrueを返す」関数に空配列を渡したらtrueかfalseか?」記事へのコメント

  • by Anonymous Coward on 2023年06月03日 10時06分 (#4471104)

    「配列のすべての要素が条件を満たすならtrueを返す」と書かれているということは、
    前提としてはfalseであり、「条件を満たさない限りtrueにはならない」のである。
    簡単に言えばホワイトリスト式ということだ。よって、空配列を渡すと条件を満たす
    ことがないのでfalseになるのが正解である。

    対して、これが「配列のいずれかの要素が条件を満たさないならfalseを返す」
    だった場合、ブラックリスト式なので、前提としてtrueであり、「条件を満たさない
    要素があった場合のみfalseになる」ので、空配列を渡すと、条件を満たさないことが
    ないので「true」になる。

    いいプログラマは、こういう論理の落とし穴を理解してうまく対処できるプログラマ
    である。

    • by Anonymous Coward

      関数の仕様は空集合の入力においてvacuously trueの原則に従います。
      ・JavaScriptのarrayのanyメソッドは、空の配列に対してはあらゆる条件でtrueを戻す。
      ・Pythonのall関数は、空のリストに対してはあらゆる条件でtrueを戻す。
      ・RustのIterator::all関数は、ゼロ要素の場合あらゆるpredicatorでtrueを戻す。

      空の配列を入力してfalseを戻す関数というのは、一般的な常識から考えて全く予想外の動作であり、
      無用な混乱を呼ぶので避けた方が良いと思う。

      • by Anonymous Coward

        その原則は明示的な仕様がない場合の話で、明確に定義されてるんだから、そこに従わざるを得ない。

        • by Anonymous Coward

          「配列のすべての要素が条件を満たすならtrueを返す」という条件なら、空の配列を渡せば数学的には疑問の余地なくTrueになる。
          空集合はすべての集合の部分集合であると定義されているので、仮に空集合がFalseになるなら、どのような集合を入力する場合でもFalseになってしまうので。

          あとはプログラミング言語の方言というか、経験的な物がどうかという点だが、その点でも普通はTrueだというのが前のコメント。

          • by Anonymous Coward

            > 空集合はすべての集合の部分集合であると定義されているので、

            勝手に仕様を書き足してんじゃねえよクソが。

            • by Anonymous Coward

              俺はゼロで割ってはいけないなんて知らなかった!仕様に書いとけクソが!
              なんてプログラマにとっての常識を持ち合わせてませんってな自己アピールして良いことありそう?

        • by Anonymous Coward

          明示的な仕様を決める人がこういった背景を理解しているのならば、この関数(関数Fとする)を必ず空集合の入力にtrueを戻す設計にするでしょう。それが常識的な動作であり、当然そうなると皆が期待している。

          計算機は本質的に数学の問題を解く機械であり、数学の法則に従った設計が最も効率が良くなる。たとえば、関数Fを実装するとき中でライブラリ関数を呼び出すとしたら、空配列の場合の特別な分岐処理は不要で、中でそのままライブラリ関数を呼び出すだけで良くなる。
          もしも関数Fを呼び出す関数(関数G)が、関数Fが空の配列の場合にtrueが戻すのが都合が悪い場合、関数GはFを呼ぶ前にその特別な処理に移行すればよい。関数Gが、関数Fが空の配列の場合にtrueを戻す動作が都合が良い場合そのままFを呼び出せばよい。Fの中で例外をthrowし、Gがそれをcatchする設計は、全体として一般的なやり方ではないから読みにくいし、動作効率の面で問題が起きる場合がある。

          • by Anonymous Coward

            書いてないことを勝手に読み取ると、多くの人が迷惑する。仕様が間違ってるとしても、それに依拠している人がいるんだから、それに従わないと。

      • by Anonymous Coward

        「コンテナに対してboolを問う処理」は集合論に準拠するのがセオリーですね。
        実在する要素が大事な場合はtrue/falseでなく「その要素(群)」が返り値になるはずで、
        (find(...) != null) や (filter(...).length > 0) のほうが可読性も良くなります。

        案の定コメント欄もこれだけ伸びましたが、それらのコメントを眺めていても
        返り値true/falseでそのドメインに至るかどうかの話に帰結している気がします。

    • by Anonymous Coward

      勝手に前提とか持ち出して対処した気になってる自称いいプログラマ
      存在しないアナを埋めたつもりでいらんコブを増やしてる

      「配列のすべての要素が条件を満たすならtrueを返す」なら、『空配列を渡すと、条件を満たさないことがないので「true」になる』っていってるのと同じで論理的に破綻してる
      謎の条件(前提)を加えたせいで、自分が本質的に全く別物を実装してるのにも気が付かないプログラマ

    • by Anonymous Coward

      世の標準ライブラリはほぼ全て間違えていると言うことか。
      考え方を改めた方がいいのでは?

    • by Anonymous Coward

      多分ですが、空配列をそのまま真偽判定したら、となんらかの条件を判定する関数に空配列を渡したら、が混ざってる人が多いってことなんではないかと。
      そうであれば true 派の意見はまぁ、わかります。問題を読み違えてますけど。

      作る人の立場にたてば、空配列には条件を満たす値は入っていないので false、としたいところ。
      使う人の立場だと、何らかの処理で持ってきた配列をそのまま渡す事は十分想定されるので、配列が空の場合はありえる。その上で条件に合う要素があるかないかを返して欲しい。

      例外派については論外。
      配列でないものを渡したわけでも配列の型を間違えたわけでもないのに例外を返されると面倒。制限事項があるならドキュメントに書いてほしいが、こんな制限はイヤだ。

      • by Anonymous Coward

        作る立場であれば、1つ要素をチェックして、条件に合わないものが来た時点でfalseを返す、リストの要素をすべてチェックし終えたらtrueを返すようにしたいので、空リストはtrueですね。

        使う方としては、空リストを受け付けない処理であればisEmptyでチェックして処理を分けるし、空リストを受け付ける処理であれば、条件に合わない要素があるリストと同様に扱われるのは面倒なのでtrueが良い。

    • by Anonymous Coward

      ドキュメントが悪いよね。
      そして問題の設定も同様に悪い。
      「配列のすべての要素が条件を満たすならtrueを返す」関数が「空の配列を渡したらfalseを返すかtrueを返すか」じゃなくて。
      「空の配列を渡したらtrueを返す」関数は「配列のすべての要素が条件を満たすならtrueを返す」関数なのかどうかを問うべき。
      「falsyな値を含まないときにtrueを返す」と書いてくれれば誤解しないのだけど。

    • by Anonymous Coward

      >「配列のすべての要素が条件を満たすならtrueを返す」
      を論理式で表したら
       ∀x∈{所与の配列の要素}: xが条件condを満たす --- (1)

      >「配列のいずれかの要素が条件を満たさないならfalseを返す」
      を論理式で表したら
       ¬(∃x∈{所与の配列の要素}: xが条件condを満たさない) --- (2)

      で、(1)と(2)の真理値表は一致するから(1)と(2)に論理的な違いは無く、読んだままに解釈して良くて、落とし穴というものは存在しない。

      配列が空の場合については
      (1) 「すべての要素が条件を満たすか?」というだけ話に、「かつ最低でも一つは条件を満たすこと」という別の条件を勝手に加

    • by Anonymous Coward

      すべての要素が条件を満たしてるじゃん。

      なんなら対偶とって条件を満たしていない要素が一つもない、という書き方で書き換えたほうがわかりやすいかな。。

      • by Anonymous Coward

        その対偶は間違ってるから結論も間違ってる。

        「配列のすべての要素が条件を満たすならtrueを返す」の対偶は
        「falseを返すなら配列のすべての要素が条件を満たすわけではない」

        これ以外の対偶の取り方をした場合、配列の空要素には対応できない。砕けて言うと、命題の真偽がメタレベルに及べばパラドックス化するからね。

        • by Anonymous Coward

          「配列のすべての要素が条件を満たす」の否定は「配列の1つ以上の要素が条件を満たさない」なので、

          「配列のすべての要素が条件を満たすならtrueを返す」の対偶は
          「falseを返すなら配列の1つ以上の要素が条件を満たさない」

          ですね。人間という括りの中で「完全無欠の人間」ではない人間は「欠点のある人間」であって「無能な人間」とは限りません。#4471579のACの方もそうですが、「対偶」を勉強し直したほうが良いのではないかと。

          なお、ここで言っている「すべて」というのは「100%」のことですので、要素数が0の場合の「すべて」は「0個」と言う意味になります。日常的には「すべて」の意味するところが0以外の範囲で捉えられていることが多いので、状況に応じて0の場合の対応を決める必要があります。例えば、「全ての問題を修復しました。修復した問題は0件です。」と表示されても混乱の元でしかありません。

          • by Anonymous Coward

            「問題を修復できませんでした。修復した問題は0件中0件ですです。」とエラー出ても混乱のもとでしかないけどな。
            内部的には全ての問題を修復できたとしてTrueを返し、エラー表示しないほうが問題が少ない。
            だからこそ、多くの関数で空の配列を渡した場合Trueを返す実装になってる。

            • by Anonymous Coward

              うむ、空配列の場合を特別扱いした気分は分かるんだけど、その特別扱いした結果Trueになるよね
              Falseにするのがイケてるケースがなかなか思いつかない

            • by Anonymous Coward

              空リストのときにtrueを返す以外のことをしろと言いたいわけではありません。言いたいのは、要素数が0個のときの「すべて」が誤解を招きやすいので、そういう表現をさけるべきということです。仕様書であれば、要素数が0の場合について言及する、もしくは、「条件を満たさない要素が1つもない」と言う表現をするということ。メッセージの文言であれば要素数が0の場合に「すべて」と言う表現を使わないことです。表示の問題だけなので、ロジック自体をいじる必要はなく、要素数に応じた表現を適用するだけの話です。

にわかな奴ほど語りたがる -- あるハッカー

処理中...