アカウント名:
パスワード:
「配列のすべての要素が条件を満たすならtrueを返す」と書かれているということは、前提としてはfalseであり、「条件を満たさない限りtrueにはならない」のである。簡単に言えばホワイトリスト式ということだ。よって、空配列を渡すと条件を満たすことがないのでfalseになるのが正解である。
対して、これが「配列のいずれかの要素が条件を満たさないならfalseを返す」だった場合、ブラックリスト式なので、前提としてtrueであり、「条件を満たさない要素があった場合のみfalseになる」ので、空配列を渡すと、条件を満たさないことがないので「true」になる。
いいプログラマは、こういう論理の落とし穴を理解してうまく対処できるプログラマである。
関数の仕様は空集合の入力においてvacuously trueの原則に従います。・JavaScriptのarrayのanyメソッドは、空の配列に対してはあらゆる条件でtrueを戻す。・Pythonのall関数は、空のリストに対してはあらゆる条件でtrueを戻す。・RustのIterator::all関数は、ゼロ要素の場合あらゆるpredicatorでtrueを戻す。
空の配列を入力してfalseを戻す関数というのは、一般的な常識から考えて全く予想外の動作であり、無用な混乱を呼ぶので避けた方が良いと思う。
その原則は明示的な仕様がない場合の話で、明確に定義されてるんだから、そこに従わざるを得ない。
「配列のすべての要素が条件を満たすならtrueを返す」という条件なら、空の配列を渡せば数学的には疑問の余地なくTrueになる。空集合はすべての集合の部分集合であると定義されているので、仮に空集合がFalseになるなら、どのような集合を入力する場合でもFalseになってしまうので。
あとはプログラミング言語の方言というか、経験的な物がどうかという点だが、その点でも普通はTrueだというのが前のコメント。
> 空集合はすべての集合の部分集合であると定義されているので、
勝手に仕様を書き足してんじゃねえよクソが。
俺はゼロで割ってはいけないなんて知らなかった!仕様に書いとけクソが!なんてプログラマにとっての常識を持ち合わせてませんってな自己アピールして良いことありそう?
> プログラマにとって違います。数字を扱うすべての人にとって、です。仕様書に1+1=2と書いとけ!みんなが判ると思うな!というぐらいに情けない話でしょう。数字を扱わないならまあ……知らなくてもいいですかね。
明示的な仕様を決める人がこういった背景を理解しているのならば、この関数(関数Fとする)を必ず空集合の入力にtrueを戻す設計にするでしょう。それが常識的な動作であり、当然そうなると皆が期待している。
計算機は本質的に数学の問題を解く機械であり、数学の法則に従った設計が最も効率が良くなる。たとえば、関数Fを実装するとき中でライブラリ関数を呼び出すとしたら、空配列の場合の特別な分岐処理は不要で、中でそのままライブラリ関数を呼び出すだけで良くなる。もしも関数Fを呼び出す関数(関数G)が、関数Fが空の配列の場合にtrueが戻すのが都合が悪い場合、関数GはFを呼ぶ前にその特別な処理に移行すればよい。関数Gが、関数Fが空の配列の場合にtrueを戻す動作が都合が良い場合そのままFを呼び出せばよい。Fの中で例外をthrowし、Gがそれをcatchする設計は、全体として一般的なやり方ではないから読みにくいし、動作効率の面で問題が起きる場合がある。
書いてないことを勝手に読み取ると、多くの人が迷惑する。仕様が間違ってるとしても、それに依拠している人がいるんだから、それに従わないと。
「コンテナに対してboolを問う処理」は集合論に準拠するのがセオリーですね。実在する要素が大事な場合はtrue/falseでなく「その要素(群)」が返り値になるはずで、(find(...) != null) や (filter(...).length > 0) のほうが可読性も良くなります。
案の定コメント欄もこれだけ伸びましたが、それらのコメントを眺めていても返り値true/falseでそのドメインに至るかどうかの話に帰結している気がします。
勝手に前提とか持ち出して対処した気になってる自称いいプログラマ存在しないアナを埋めたつもりでいらんコブを増やしてる
「配列のすべての要素が条件を満たすならtrueを返す」なら、『空配列を渡すと、条件を満たさないことがないので「true」になる』っていってるのと同じで論理的に破綻してる謎の条件(前提)を加えたせいで、自分が本質的に全く別物を実装してるのにも気が付かないプログラマ
世の標準ライブラリはほぼ全て間違えていると言うことか。考え方を改めた方がいいのでは?
何度か考えたのですが、0個の要素全てについて条件判定した結果、OKなのでtrueになる。
全くピーマンが入っていない料理を平らげた子供が「出されたピーマンを全て食べました。」と言ったとき、それは嘘ではないからtrueです。
最低でも一度以上判定をしなければならないなんてどこにも書かれてない。勝手に仕様を書き足すんじゃねえよクソが。
ほんと世の中勝手に仕様を書き足すクソばっかりで驚きだよ。
いいか?配列が空配列ということは、要素がないということだ。つまり条件判定をしないからエラーにならない配列外なのに判定走らすコードを書くやつはプログラマとして論外だからなそしてそれは0個の要素全てが「条件を満たす」という結果とイコールか?その通りだw
勝手に数学を無視した俺様が思う最強仕様とか別世界の話持ってくるなっつの。バカじゃねえの?
> そしてそれは0個の要素全てが「条件を満たす」という結果とイコールか?その通りだw
それは数学での話であってプログラムの話ではないな。勝手に仕様を書き足してんじゃねえよクソが。
多分ですが、空配列をそのまま真偽判定したら、となんらかの条件を判定する関数に空配列を渡したら、が混ざってる人が多いってことなんではないかと。そうであれば true 派の意見はまぁ、わかります。問題を読み違えてますけど。
作る人の立場にたてば、空配列には条件を満たす値は入っていないので false、としたいところ。使う人の立場だと、何らかの処理で持ってきた配列をそのまま渡す事は十分想定されるので、配列が空の場合はありえる。その上で条件に合う要素があるかないかを返して欲しい。
例外派については論外。配列でないものを渡したわけでも配列の型を間違えたわけでもないのに例外を返されると面倒。制限事項があるならドキュメントに書いてほしいが、こんな制限はイヤだ。
作る立場であれば、1つ要素をチェックして、条件に合わないものが来た時点でfalseを返す、リストの要素をすべてチェックし終えたらtrueを返すようにしたいので、空リストはtrueですね。
使う方としては、空リストを受け付けない処理であればisEmptyでチェックして処理を分けるし、空リストを受け付ける処理であれば、条件に合わない要素があるリストと同様に扱われるのは面倒なのでtrueが良い。
ドキュメントが悪いよね。そして問題の設定も同様に悪い。「配列のすべての要素が条件を満たすならtrueを返す」関数が「空の配列を渡したらfalseを返すかtrueを返すか」じゃなくて。「空の配列を渡したらtrueを返す」関数は「配列のすべての要素が条件を満たすならtrueを返す」関数なのかどうかを問うべき。「falsyな値を含まないときにtrueを返す」と書いてくれれば誤解しないのだけど。
>「配列のすべての要素が条件を満たすならtrueを返す」を論理式で表したら ∀x∈{所与の配列の要素}: xが条件condを満たす --- (1)
>「配列のいずれかの要素が条件を満たさないならfalseを返す」を論理式で表したら ¬(∃x∈{所与の配列の要素}: xが条件condを満たさない) --- (2)
で、(1)と(2)の真理値表は一致するから(1)と(2)に論理的な違いは無く、読んだままに解釈して良くて、落とし穴というものは存在しない。
配列が空の場合については(1) 「すべての要素が条件を満たすか?」というだけ話に、「かつ最低でも一つは条件を満たすこと」という別の条件を勝手に加
すべての要素が条件を満たしてるじゃん。
なんなら対偶とって条件を満たしていない要素が一つもない、という書き方で書き換えたほうがわかりやすいかな。。
その対偶は間違ってるから結論も間違ってる。
「配列のすべての要素が条件を満たすならtrueを返す」の対偶は「falseを返すなら配列のすべての要素が条件を満たすわけではない」
これ以外の対偶の取り方をした場合、配列の空要素には対応できない。砕けて言うと、命題の真偽がメタレベルに及べばパラドックス化するからね。
「配列のすべての要素が条件を満たす」の否定は「配列の1つ以上の要素が条件を満たさない」なので、
「配列のすべての要素が条件を満たすならtrueを返す」の対偶は「falseを返すなら配列の1つ以上の要素が条件を満たさない」
ですね。人間という括りの中で「完全無欠の人間」ではない人間は「欠点のある人間」であって「無能な人間」とは限りません。#4471579のACの方もそうですが、「対偶」を勉強し直したほうが良いのではないかと。
なお、ここで言っている「すべて」というのは「100%」のことですので、要素数が0の場合の「すべて」は「0個」と言う意味になります。日常的には「すべて」の意味するところが0以外の範囲で捉えられていることが多いので、状況に応じて0の場合の対応を決める必要があります。例えば、「全ての問題を修復しました。修復した問題は0件です。」と表示されても混乱の元でしかありません。
「問題を修復できませんでした。修復した問題は0件中0件ですです。」とエラー出ても混乱のもとでしかないけどな。内部的には全ての問題を修復できたとしてTrueを返し、エラー表示しないほうが問題が少ない。だからこそ、多くの関数で空の配列を渡した場合Trueを返す実装になってる。
うむ、空配列の場合を特別扱いした気分は分かるんだけど、その特別扱いした結果TrueになるよねFalseにするのがイケてるケースがなかなか思いつかない
空リストのときにtrueを返す以外のことをしろと言いたいわけではありません。言いたいのは、要素数が0個のときの「すべて」が誤解を招きやすいので、そういう表現をさけるべきということです。仕様書であれば、要素数が0の場合について言及する、もしくは、「条件を満たさない要素が1つもない」と言う表現をするということ。メッセージの文言であれば要素数が0の場合に「すべて」と言う表現を使わないことです。表示の問題だけなので、ロジック自体をいじる必要はなく、要素数に応じた表現を適用するだけの話です。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
にわかな奴ほど語りたがる -- あるハッカー
迷う余地などなく「false」を返すのが正しい。 (スコア:0)
「配列のすべての要素が条件を満たすならtrueを返す」と書かれているということは、
前提としてはfalseであり、「条件を満たさない限りtrueにはならない」のである。
簡単に言えばホワイトリスト式ということだ。よって、空配列を渡すと条件を満たす
ことがないのでfalseになるのが正解である。
対して、これが「配列のいずれかの要素が条件を満たさないならfalseを返す」
だった場合、ブラックリスト式なので、前提としてtrueであり、「条件を満たさない
要素があった場合のみfalseになる」ので、空配列を渡すと、条件を満たさないことが
ないので「true」になる。
いいプログラマは、こういう論理の落とし穴を理解してうまく対処できるプログラマ
である。
Re: (スコア:0)
関数の仕様は空集合の入力においてvacuously trueの原則に従います。
・JavaScriptのarrayのanyメソッドは、空の配列に対してはあらゆる条件でtrueを戻す。
・Pythonのall関数は、空のリストに対してはあらゆる条件でtrueを戻す。
・RustのIterator::all関数は、ゼロ要素の場合あらゆるpredicatorでtrueを戻す。
空の配列を入力してfalseを戻す関数というのは、一般的な常識から考えて全く予想外の動作であり、
無用な混乱を呼ぶので避けた方が良いと思う。
Re: (スコア:0)
その原則は明示的な仕様がない場合の話で、明確に定義されてるんだから、そこに従わざるを得ない。
Re: (スコア:0)
「配列のすべての要素が条件を満たすならtrueを返す」という条件なら、空の配列を渡せば数学的には疑問の余地なくTrueになる。
空集合はすべての集合の部分集合であると定義されているので、仮に空集合がFalseになるなら、どのような集合を入力する場合でもFalseになってしまうので。
あとはプログラミング言語の方言というか、経験的な物がどうかという点だが、その点でも普通はTrueだというのが前のコメント。
Re: (スコア:0)
> 空集合はすべての集合の部分集合であると定義されているので、
勝手に仕様を書き足してんじゃねえよクソが。
Re: (スコア:0)
俺はゼロで割ってはいけないなんて知らなかった!仕様に書いとけクソが!
なんてプログラマにとっての常識を持ち合わせてませんってな自己アピールして良いことありそう?
Re: (スコア:0)
> プログラマにとって
違います。数字を扱うすべての人にとって、です。
仕様書に1+1=2と書いとけ!みんなが判ると思うな!というぐらいに情けない話でしょう。
数字を扱わないならまあ……知らなくてもいいですかね。
Re:迷う余地などなく「false」を返すのが正しい。 (スコア:1)
// 数学からすると 1+1 = 0か1か2か
Re: (スコア:0)
明示的な仕様を決める人がこういった背景を理解しているのならば、この関数(関数Fとする)を必ず空集合の入力にtrueを戻す設計にするでしょう。それが常識的な動作であり、当然そうなると皆が期待している。
計算機は本質的に数学の問題を解く機械であり、数学の法則に従った設計が最も効率が良くなる。たとえば、関数Fを実装するとき中でライブラリ関数を呼び出すとしたら、空配列の場合の特別な分岐処理は不要で、中でそのままライブラリ関数を呼び出すだけで良くなる。
もしも関数Fを呼び出す関数(関数G)が、関数Fが空の配列の場合にtrueが戻すのが都合が悪い場合、関数GはFを呼ぶ前にその特別な処理に移行すればよい。関数Gが、関数Fが空の配列の場合にtrueを戻す動作が都合が良い場合そのままFを呼び出せばよい。Fの中で例外をthrowし、Gがそれをcatchする設計は、全体として一般的なやり方ではないから読みにくいし、動作効率の面で問題が起きる場合がある。
Re: (スコア:0)
書いてないことを勝手に読み取ると、多くの人が迷惑する。仕様が間違ってるとしても、それに依拠している人がいるんだから、それに従わないと。
Re: (スコア:0)
「コンテナに対してboolを問う処理」は集合論に準拠するのがセオリーですね。
実在する要素が大事な場合はtrue/falseでなく「その要素(群)」が返り値になるはずで、
(find(...) != null) や (filter(...).length > 0) のほうが可読性も良くなります。
案の定コメント欄もこれだけ伸びましたが、それらのコメントを眺めていても
返り値true/falseでそのドメインに至るかどうかの話に帰結している気がします。
Re: (スコア:0)
勝手に前提とか持ち出して対処した気になってる自称いいプログラマ
存在しないアナを埋めたつもりでいらんコブを増やしてる
「配列のすべての要素が条件を満たすならtrueを返す」なら、『空配列を渡すと、条件を満たさないことがないので「true」になる』っていってるのと同じで論理的に破綻してる
謎の条件(前提)を加えたせいで、自分が本質的に全く別物を実装してるのにも気が付かないプログラマ
Re: (スコア:0)
世の標準ライブラリはほぼ全て間違えていると言うことか。
考え方を改めた方がいいのでは?
Re:迷う余地などなく「false」を返すのが正しい。 (スコア:1)
何度か考えたのですが、0個の要素全てについて条件判定した結果、OKなのでtrueになる。
全くピーマンが入っていない料理を平らげた子供が「出されたピーマンを全て食べました。」と言ったとき、それは嘘ではないからtrueです。
Re: (スコア:0)
最低でも一度以上判定をしなければならないなんてどこにも書かれてない。
勝手に仕様を書き足すんじゃねえよクソが。
Re: (スコア:0)
ほんと世の中勝手に仕様を書き足すクソばっかりで驚きだよ。
いいか?配列が空配列ということは、要素がないということだ。
つまり条件判定をしないからエラーにならない
配列外なのに判定走らすコードを書くやつはプログラマとして論外だからな
そしてそれは0個の要素全てが「条件を満たす」という結果とイコールか?その通りだw
勝手に数学を無視した俺様が思う最強仕様とか別世界の話持ってくるなっつの。バカじゃねえの?
Re: (スコア:0)
> そしてそれは0個の要素全てが「条件を満たす」という結果とイコールか?その通りだw
それは数学での話であってプログラムの話ではないな。
勝手に仕様を書き足してんじゃねえよクソが。
Re: (スコア:0)
多分ですが、空配列をそのまま真偽判定したら、となんらかの条件を判定する関数に空配列を渡したら、が混ざってる人が多いってことなんではないかと。
そうであれば true 派の意見はまぁ、わかります。問題を読み違えてますけど。
作る人の立場にたてば、空配列には条件を満たす値は入っていないので false、としたいところ。
使う人の立場だと、何らかの処理で持ってきた配列をそのまま渡す事は十分想定されるので、配列が空の場合はありえる。その上で条件に合う要素があるかないかを返して欲しい。
例外派については論外。
配列でないものを渡したわけでも配列の型を間違えたわけでもないのに例外を返されると面倒。制限事項があるならドキュメントに書いてほしいが、こんな制限はイヤだ。
Re: (スコア:0)
作る立場であれば、1つ要素をチェックして、条件に合わないものが来た時点でfalseを返す、リストの要素をすべてチェックし終えたらtrueを返すようにしたいので、空リストはtrueですね。
使う方としては、空リストを受け付けない処理であればisEmptyでチェックして処理を分けるし、空リストを受け付ける処理であれば、条件に合わない要素があるリストと同様に扱われるのは面倒なのでtrueが良い。
Re: (スコア:0)
ドキュメントが悪いよね。
そして問題の設定も同様に悪い。
「配列のすべての要素が条件を満たすならtrueを返す」関数が「空の配列を渡したらfalseを返すかtrueを返すか」じゃなくて。
「空の配列を渡したらtrueを返す」関数は「配列のすべての要素が条件を満たすならtrueを返す」関数なのかどうかを問うべき。
「falsyな値を含まないときにtrueを返す」と書いてくれれば誤解しないのだけど。
Re: (スコア:0)
>「配列のすべての要素が条件を満たすならtrueを返す」
を論理式で表したら
∀x∈{所与の配列の要素}: xが条件condを満たす --- (1)
>「配列のいずれかの要素が条件を満たさないならfalseを返す」
を論理式で表したら
¬(∃x∈{所与の配列の要素}: xが条件condを満たさない) --- (2)
で、(1)と(2)の真理値表は一致するから(1)と(2)に論理的な違いは無く、読んだままに解釈して良くて、落とし穴というものは存在しない。
配列が空の場合については
(1) 「すべての要素が条件を満たすか?」というだけ話に、「かつ最低でも一つは条件を満たすこと」という別の条件を勝手に加
Re: (スコア:0)
すべての要素が条件を満たしてるじゃん。
なんなら対偶とって条件を満たしていない要素が一つもない、という書き方で書き換えたほうがわかりやすいかな。。
Re: (スコア:0)
その対偶は間違ってるから結論も間違ってる。
「配列のすべての要素が条件を満たすならtrueを返す」の対偶は
「falseを返すなら配列のすべての要素が条件を満たすわけではない」
これ以外の対偶の取り方をした場合、配列の空要素には対応できない。砕けて言うと、命題の真偽がメタレベルに及べばパラドックス化するからね。
Re: (スコア:0)
「配列のすべての要素が条件を満たす」の否定は「配列の1つ以上の要素が条件を満たさない」なので、
「配列のすべての要素が条件を満たすならtrueを返す」の対偶は
「falseを返すなら配列の1つ以上の要素が条件を満たさない」
ですね。人間という括りの中で「完全無欠の人間」ではない人間は「欠点のある人間」であって「無能な人間」とは限りません。#4471579のACの方もそうですが、「対偶」を勉強し直したほうが良いのではないかと。
なお、ここで言っている「すべて」というのは「100%」のことですので、要素数が0の場合の「すべて」は「0個」と言う意味になります。日常的には「すべて」の意味するところが0以外の範囲で捉えられていることが多いので、状況に応じて0の場合の対応を決める必要があります。例えば、「全ての問題を修復しました。修復した問題は0件です。」と表示されても混乱の元でしかありません。
Re: (スコア:0)
「問題を修復できませんでした。修復した問題は0件中0件ですです。」とエラー出ても混乱のもとでしかないけどな。
内部的には全ての問題を修復できたとしてTrueを返し、エラー表示しないほうが問題が少ない。
だからこそ、多くの関数で空の配列を渡した場合Trueを返す実装になってる。
Re: (スコア:0)
うむ、空配列の場合を特別扱いした気分は分かるんだけど、その特別扱いした結果Trueになるよね
Falseにするのがイケてるケースがなかなか思いつかない
Re: (スコア:0)
空リストのときにtrueを返す以外のことをしろと言いたいわけではありません。言いたいのは、要素数が0個のときの「すべて」が誤解を招きやすいので、そういう表現をさけるべきということです。仕様書であれば、要素数が0の場合について言及する、もしくは、「条件を満たさない要素が1つもない」と言う表現をするということ。メッセージの文言であれば要素数が0の場合に「すべて」と言う表現を使わないことです。表示の問題だけなので、ロジック自体をいじる必要はなく、要素数に応じた表現を適用するだけの話です。