[解決済み】NULLのない言語についての最適な説明
質問
プログラマがNULLエラーや例外について文句を言っていると、しばしば誰かがNULLなしでどうするのかと聞いてきます。
オプション型のカッコよさはなんとなくわかっているのですが、それをうまく表現する知識も言語スキルもないのです。とは何ですか? すごい について、一般のプログラマが親しみやすいように書かれた説明で、その人に向けて発信できるようなものを教えてください。
- 参照やポインタがデフォルトでnullになることの好ましくない点
-
オプションタイプはどのように機能するか?
- パターンマッチと
- 単項式内包
- nilを食べるメッセージなどの代替案
- (その他、見落としていた点)
解決方法は?
なぜnullが望ましくないかを簡潔にまとめると 無意味な状態は表現可能であってはならない .
例えば、ドアをモデル化するとしよう。 開いている状態、閉まっているが鍵がかかっていない状態、閉まっているが鍵がかかっている状態の3つのうち1つを取ることができる。 この場合、次のようにモデル化することができます。
class Door
private bool isShut
private bool isLocked
というように、3つの状態をこの2つのブール変数に対応させる方法は明らかです。 しかし、これでは4つ目の望ましくない状態が利用可能なままです。
isShut==false && isLocked==true
. 私が表現として選んだ型はこの状態を認めるので、クラスがこの状態にならないようにするために精神的な努力をしなければなりません(おそらく、明示的に不変性をコーディングすることによって)。 これに対して、代数的なデータ型やチェックされた列挙型を持つ言語を使っている場合、クラスがこのような状態にならないようにするために、精神的な努力をしなければなりません。
type DoorState =
| Open | ShutAndUnlocked | ShutAndLocked
を定義することができます。
class Door
private DoorState state
で、もう心配はない。 のインスタンスが取り得る状態は3つだけであることが型システムによって保証されます。
class Door
になるようにします。 これこそ型システムの得意とするところであり、コンパイル時にあらゆる種類のエラーを明示的に排除することができるのです。
の問題点は
null
は、すべての参照型がその空間でこの余分な状態を取得することであり、それは一般的に望ましくないことです。 A
string
変数は、任意の文字列である可能性もあれば、このクレイジーな余分な
null
の値は、私の問題領域には当てはまりません。 A
Triangle
オブジェクトは3つの
Point
を持ち、それ自体が
X
と
Y
の値ですが、残念ながら
Point
または
Triangle
は、私が取り組んでいるグラフの領域では無意味な、このクレイジーなnull値であるかもしれません。 などなど。
存在しないかもしれない値をモデル化するつもりなら、それを明示的に選択すべきです。 もし私が人をモデル化する方法が、すべての
Person
には
FirstName
と
LastName
が、一部の人しか持っていない。
MiddleName
のようなことを言いたいのです。
class Person
private string FirstName
private Option<string> MiddleName
private string LastName
ここで
string
は null でない型であると仮定します。 そうすれば、トリッキーな不変量が設定されることはなく、予期せぬ
NullReferenceException
は、誰かの名前の長さを計算しようとしたときに発生します。 型システムによって
MiddleName
である可能性を考慮しています。
None
を処理するすべてのコードに対して
FirstName
は、そこに値があるものと考えて差し支えない。
ですから、例えば、上記の型を使って、このような愚かな関数をオーサリングすることができます。
let TotalNumCharsInPersonsName(p:Person) =
let middleLen = match p.MiddleName with
| None -> 0
| Some(s) -> s.Length
p.FirstName.Length + middleLen + p.LastName.Length
を心配する必要はありません。 一方、文字列のような型にヌル参照可能な言語では、以下のように仮定します。
class Person
private string FirstName
private string MiddleName
private string LastName
のようなオーサリングをすることになります。
let TotalNumCharsInPersonsName(p:Person) =
p.FirstName.Length + p.MiddleName.Length + p.LastName.Length
これは、入力される Person オブジェクトがすべて非 null という不変条件を持っていない場合に吹き飛んでしまいます。
let TotalNumCharsInPersonsName(p:Person) =
(if p.FirstName=null then 0 else p.FirstName.Length)
+ (if p.MiddleName=null then 0 else p.MiddleName.Length)
+ (if p.LastName=null then 0 else p.LastName.Length)
または
let TotalNumCharsInPersonsName(p:Person) =
p.FirstName.Length
+ (if p.MiddleName=null then 0 else p.MiddleName.Length)
+ p.LastName.Length
と仮定すると
p
あるいは、異なるタイプの例外を投げるようなチェックを行うか、あるいは誰にもわからないことです。 このようなおかしな実装の選択や考えなければならないことが出てくるのは、この馬鹿げたrepresentable-valueがあるからで、それはあなたが望んでいない、あるいは必要ないものです。
Nullは通常、不必要な複雑さを追加します。 複雑さはすべてのソフトウェアの敵であり、合理的であればいつでも複雑さを減らすように努力すべきです。
(このような単純な例でさえも、さらに複雑であることに注意してください。 たとえ
FirstName
にすることはできません。
null
, a
string
を表すことができます。
""
(空文字列)であり、これもおそらく我々がモデル化しようと思っている人名ではないでしょう。 このように、Nullにならない文字列であっても、意味のない値を表現している可能性があるのです。 この場合も、実行時の不変条件や条件コードで対処するか、あるいは型システム(たとえば
NonEmptyString
という型があります)。 後者はあまりお勧めできません(quot;good" 型はしばしば共通の操作のセットに対して "closed" ですし、例えば
NonEmptyString
に対して閉じているわけではありません。
.SubString(0,0)
) が、設計空間におけるより多くのポイントを示している。 結局のところ、どのような型システムであっても、取り除くのに非常に適した複雑さと、本質的に取り除くのが難しい複雑さがあるのです。 このトピックで重要なのは、ほとんどの場合
あらゆる
型システムにおいて、quot;nullable references by default" から "non-nullable references by default" への変更は、ほぼ常に、型システムの複雑さを解消し、ある種のエラーや無意味な状態を排除する上で非常に優れたものにする単純な変更なのだそうです。 だから、多くの言語がこのエラーを何度も何度も繰り返しているのは、かなり異常なことなのだ)。
関連
-
[解決済み] JavaScriptで空文字列/未定義文字列/null文字列をチェックするにはどうすればよいですか?
-
[解決済み] JavaScriptでNULL、未定義、空白の変数をチェックする標準的な関数はありますか?
-
[解決済み] 変数が「未定義」または「NULL」であるかどうかを判断するにはどうすればよいですか?
-
[解決済み] オブジェクトのためのマップ関数(配列の代わりに)
-
[解決済み] instanceofを呼び出す前にnullチェックは必要ですか?
-
[解決済み] JavaScriptのnullとundefinedの違いは何ですか?
-
[解決済み] Pythonでnullオブジェクトを参照する
-
[解決済み] カラムの変更:NULLをNOT NULLに変更する
-
[解決済み] 静的型付け言語と動的型付け言語の違いは何ですか?
-
[解決済み] Spring の @Autowired フィールドが NULL になっているのはなぜですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン