(const
をキャストするような)特定の実行ではなく、C++のようなconst
のアイデアに興味があります。
C#を例にとると、C++のようなconstが欠けており、その理由は通常の人と時間です。ここでさらにC#チームはconst
のC++実行を見て、CLRをマーケティングしており、この時点で十分であったようです( c#とconstパラメーターにconstメンバーメソッドがない理由 を参照)。ありがとうスヴィック)。 weがそれよりも先に移動した場合、他に何かありますか?
もっと深いものはありますか?たとえば、マルチ継承を例にとります。通常、(ユーザーにとって)把握するのは難しいと考えられているため、(ひし形の問題のように)言語に追加されません。
const
の[〜#〜] nature [〜#〜]に言語に適しているという問題を引き起こす何かがありますかそれを避けるために? const
を深くするか浅くするかを決定するようなもの(const
コンテナーがあると、新しい要素を追加したり、既存の要素を変更したりできないことを意味します。要素が参照型の場合はどうなりますか?)
[〜#〜] update [〜#〜]:C#について言及しているため、歴史的な観点から、潜在的な問題の性質に興味がありますconst
を言語に変換します。
これは言語の問題ではありません。現在の傾向や人気などの要素は無視してください-技術的な問題にのみ興味があります-ありがとう
これが適しているかどうか確認してください。ただし、標準MLなどの関数型言語では、デフォルトですべてが不変です。変異は、一般的なref
erence型を通じてサポートされます。つまり、int
変数は不変であり、ref int
変数はint
sの可変コンテナーです。基本的に、変数は数学的な意味で real 変数(不明だが固定値)であり、ref
sは命令型プログラミングの意味での「変数」です-書き込みと読み取りが可能なメモリセルから。 (私はそれらを assignables と呼びます。)
const
の問題は2つあると思います。まず、C++にはガベージコレクションがありません。これは、重要な 永続的なデータ構造 にするために必要です。 const
must は意味をなさないように深くする必要がありますが、C++で完全に不変の値を持つことは現実的ではありません。
次に、C++では、const
をオプトアウトするのではなく、オプトアウトする必要があります。しかし、const
の何かを忘れて後で修正すると、@ RobYの回答で言及されている「const poisoning」の状況になり、const
の変更がコード全体にカスケードされます。 const
がデフォルトだった場合、const
をさかのぼって適用することはできません。さらに、const
をどこにでも追加する必要があると、コードに多くのノイズが追加されます。
それに続く主流の言語(Javaなど)は、CおよびC++の成功と考え方に大きく影響を受けていると思います。適切な例として、ガベージコレクションを使用しても、ほとんどの言語のコレクションAPIは変更可能なデータ構造を想定しています。すべてが変更可能で不変であるという事実は、人気のある言語の背後にある必須の考え方について多くのことを物語っています。
[〜#〜] edit [〜#〜]: greenoldmanのコメント を検討した後、const
は直接ではないことに気付きましたデータの不変性について; const
は、インスタンスに副作用があるかどうかをメソッドの型にエンコードします。
ミューテーションを使用して 参照的に透過的 の動作を実現することが可能です。連続して呼び出されたときに異なる値を返す関数があるとします。たとえば、stdin
から単一の文字を読み取る関数があります。この関数の結果をキャッシュ/メモ化して、参照透過的な値のストリームを生成できます。ストリームはリンクされたリストになり、そのノードは最初に値を取得しようとしたときに関数を呼び出しますが、結果をキャッシュします。したがって、stdin
にHello, world!
が含まれている場合、最初のノードの値を初めて取得しようとすると、1つのchar
が読み取られ、H
が返されます。その後、H
を読み取るための追加の呼び出しなしでchar
を返し続けます。同様に、2番目のノードは、初めて値を取得しようとしたときにchar
からstdin
を読み取り、今回はe
を返し、その結果をキャッシュします。
ここで興味深いのは、本質的にステートフルなプロセスを、ステートレスのように見えるオブジェクトに変換したことです。ただし、これを実現するには、オブジェクトの内部状態を(結果をキャッシュすることによって)変更する必要がありました。変更は、良性効果でした。ストリーム /が不変の値のように動作する場合でも、CharStream
const
を作成することは不可能です。ここで、Stream
メソッドを備えたconst
インターフェイスがあり、すべての関数がconst Streams
を想定しているとします。 CharStream
はインターフェースを実装できません!
(EDIT 2:どうやらmutable
というC++キーワードがあり、それが CharStream
const
をだまして作成できるようにする ただし、この抜け穴はconst
の保証を破壊します。const
メソッドを使用して何かが変更されないかどうかは本当にわかりません。抜け穴を明示的に要求する必要があるので、それほど悪くはないと思いますが、完全に信頼できます。名誉制度について。)
次に、高次の関数があるとします。つまり、関数を引数として他の関数に渡すことができます。 const
nessは関数のシグネチャの一部であるため、const
関数を必要とする関数への引数として、const
以外の関数を渡すことはできません。ここでconst
を盲目的に適用すると、一般性が失われます。
最後に、const
オブジェクトを操作しても、背後の外部(静的またはグローバル)状態が変化しないことは保証されないため、const
の保証は、最初に表示されるほど強力ではありません。
副作用の有無を型システムにエンコードすることが普遍的に良いことであることは私には明らかではありません。
主な問題は、プログラマーが十分にそれを使用しない傾向があるため、必要な場所にぶつかったとき、またはメンテナーがconst-correctnessを後で修正したいときに、大きな波及効果があります。 const
がなくても、完全に優れた不変のコードを書くことができます。コンパイラーはそれを強制せず、最適化するのがより困難になります。一部の人々は彼らのコンパイラが彼らを助けないことを好む。私はそれらの人々を理解していませんが、彼らはたくさんいます。
関数型言語では、ほとんどすべてがconst
であり、許可されている場合、ミュータブルであることはまれな例外です。これには、同時実行性や共有状態の推論が容易になるなど、いくつかの利点がありますが、文化が変更可能な言語を使用している場合は、慣れる必要があります。言い換えれば、const
を望まないのは人の問題であり、技術的な問題ではありません。
欠点は次のとおりです。
「const poisoning」は、constの1つの宣言が前または次の宣言でconstを使用するように強制できる場合の問題であり、それにより、前の後続の宣言でconstなどが使用される可能性があります。あなたがコントロールできないと、あなたは悪い場所で動けなくなるかもしれません。
絶対的な保証ではありません。通常、constが参照を保護するだけで、何らかの理由で基礎となる値を保護できない場合があります。 Cでも、constが到達できないEdgeケースがあり、constが提供する約束が弱められます。
一般に、業界のセンチメントは強力なコンパイル時の保証から遠ざかっているように見えますが、どれほど快適であってもあなたと私にもたらされる可能性があります。したがって、午後には、const poisoningのために、コードベースの66%に触れることに費やします。 Python男は10の完全に機能し、十分に設計され、十分にテストされ、完全に機能しているPythonモジュールです。そして、ハッキングすらしていませんでした。 。
おそらく問題は、あなたがあなたの気の利いた新しい言語の採用を得ようとしているときに、一部の専門家でさえ曖昧な潜在的に論争の的となる機能を引き継ぐのはなぜですか?
編集:短い答え、新しい言語は採用のために登るのに険しい丘を持っています。デザイナーは、採用するために必要な機能について真剣に考える必要があります。たとえば、囲碁を取ってください。 Googleは、コナンバーバリアンスタイルのデザインを選択することで、最も深い宗教的な戦いのいくつかを残酷に打ち切りました。実際、私が見たものから、言語はその方が適していると思います。
言語にconst
を追加することには、いくつかの哲学的問題があります。クラスにconst
を宣言すると、クラスは変更できなくなります。ただし、クラスはメソッド(またはミューテーター)と結合された変数のセットです。クラスの状態を一連のメソッドの背後に隠すことで抽象化を実現します。クラスが状態を非表示にするように設計されている場合、その状態を外部から変更するためのミューテーターが必要であり、それはもうconst
ではありません。したがって、const
を不変のクラスに宣言することのみが可能です。したがって、const
は、クラス(またはconst
を宣言する型)が簡単なシナリオでのみ可能と思われます...
とにかくconst
が必要ですか?私はそうは思いません。デザインが良ければ、const
がなくても簡単にできると思います。どのデータがどこに必要か、どのメソッドがデータ間メソッドであるか、どの抽象化がI/O、ネットワーク、ビューなどに必要か。その後、状態を処理するモジュールとクラスが自然に分割され、メソッドと状態を必要としない不変のクラス。
ほとんどの問題は、それ自体を保存、変換、描画できる大きな脂肪のデータオブジェクトで発生し、それをレンダラーなどに渡したいと思います。そのため、ビッグデータオブジェクトには高すぎるため、データの内容をコピーすることはできません。しかし、どちらも変更したくないので、const
のようなものが必要です。コンパイラーに設計上の欠陥を見つけさせます。ただし、これらのオブジェクトを不変のデータオブジェクトのみに分割し、メソッドを担当モジュールに実装すると、不変を保証しながら、ポインターを(のみ)渡して、データに対して実行したいことを実行できます。
C++では、一部のメソッドをconst
と宣言し、他のメソッドはミューテーターであるため、宣言しないことが可能であることを知っています。そして、しばらくしてからキャッシュが必要になり、getterがオブジェクトを変更し(遅延読み込みのため)、もうconst
ではありません。しかし、それがこの抽象化の要点でしたね?各呼び出しでどの状態が変化するかはわかりません。