web-dev-qa-db-ja.com

C ++のようなconstを言語に取り入れることの問題は何ですか?

constをキャストするような)特定の実行ではなく、C++のようなconstのアイデアに興味があります。

C#を例にとると、C++のようなconstが欠けており、その理由は通常の人と時間です。ここでさらにC#チームはconstのC++実行を見て、CLRをマーケティングしており、この時点で十分であったようです( c#とconstパラメーターにconstメンバーメソッドがない理由 を参照)。ありがとうスヴィック)。 weがそれよりも先に移動した場合、他に何かありますか?

もっと深いものはありますか?たとえば、マルチ継承を例にとります。通常、(ユーザーにとって)把握するのは難しいと考えられているため、(ひし形の問題のように)言語に追加されません。

const[〜#〜] nature [〜#〜]に言語に適しているという問題を引き起こす何かがありますかそれを避けるために? constを深くするか浅くするかを決定するようなもの(constコンテナーがあると、新しい要素を追加したり、既存の要素を変更したりできないことを意味します。要素が参照型の場合はどうなりますか?)

[〜#〜] update [〜#〜]:C#について言及しているため、歴史的な観点から、潜在的な問題の性質に興味がありますconstを言語に変換します。

これは言語の問題ではありません。現在の傾向や人気などの要素は無視してください-技術的な問題にのみ興味があります-ありがとう

18
greenoldman

これが適しているかどうか確認してください。ただし、標準MLなどの関数型言語では、デフォルトですべてが不変です。変異は、一般的なreference型を通じてサポートされます。つまり、int変数は不変であり、ref int変数はintsの可変コンテナーです。基本的に、変数は数学的な意味で real 変数(不明だが固定値)であり、refsは命令型プログラミングの意味での「変数」です-書き込みと読み取りが可能なメモリセルから。 (私はそれらを 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から単一の文字を読み取る関数があります。この関数の結果をキャッシュ/メモ化して、参照透過的な値のストリームを生成できます。ストリームはリンクされたリストになり、そのノードは最初に値を取得しようとしたときに関数を呼び出しますが、結果をキャッシュします。したがって、stdinHello, world!が含まれている場合、最初のノードの値を初めて取得しようとすると、1つのcharが読み取られ、Hが返されます。その後、Hを読み取るための追加の呼び出しなしでcharを返し続けます。同様に、2番目のノードは、初めて値を取得しようとしたときにcharからstdinを読み取り、今回はeを返し、その結果をキャッシュします。

ここで興味深いのは、本質的にステートフルなプロセスを、ステートレスのように見えるオブジェクトに変換したことです。ただし、これを実現するには、オブジェクトの内部状態を(結果をキャッシュすることによって)変更する必要がありました。変更は、良性効果でした。ストリーム /が不変の値のように動作する場合でも、CharStreamconstを作成することは不可能です。ここで、Streamメソッドを備えたconstインターフェイスがあり、すべての関数がconst Streamsを想定しているとします。 CharStreamはインターフェースを実装できません!

EDIT 2:どうやらmutableというC++キーワードがあり、それが CharStreamconstをだまして作成できるようにする ただし、この抜け穴はconstの保証を破壊します。constメソッドを使用して何かが変更されないかどうかは本当にわかりません。抜け穴を明示的に要求する必要があるので、それほど悪くはないと思いますが、完全に信頼できます。名誉制度について。)

次に、高次の関数があるとします。つまり、関数を引数として他の関数に渡すことができます。 constnessは関数のシグネチャの一部であるため、const関数を必要とする関数への引数として、const以外の関数を渡すことはできません。ここでconstを盲目的に適用すると、一般性が失われます。

最後に、constオブジェクトを操作しても、背後の外部(静的またはグローバル)状態が変化しないことは保証されないため、constの保証は、最初に表示されるほど強力ではありません。

副作用の有無を型システムにエンコードすることが普遍的に良いことであることは私には明らかではありません。

12
Doval

主な問題は、プログラマーが十分にそれを使用しない傾向があるため、必要な場所にぶつかったとき、またはメンテナーがconst-correctnessを後で修正したいときに、大きな波及効果があります。 constがなくても、完全に優れた不変のコードを書くことができます。コンパイラーはそれを強制せず、最適化するのがより困難になります。一部の人々は彼らのコンパイラが彼らを助けないことを好む。私はそれらの人々を理解していませんが、彼らはたくさんいます。

関数型言語では、ほとんどすべてがconstであり、許可されている場合、ミュータブルであることはまれな例外です。これには、同時実行性や共有状態の推論が容易になるなど、いくつかの利点がありますが、文化が変更可能な言語を使用している場合は、慣れる必要があります。言い換えれば、constを望まないのは人の問題であり、技術的な問題ではありません。

8
Karl Bielefeldt

欠点は次のとおりです。

  • 「const poisoning」は、constの1つの宣言が前または次の宣言でconstを使用するように強制できる場合の問題であり、それにより、前の後続の宣言でconstなどが使用される可能性があります。あなたがコントロールできないと、あなたは悪い場所で動けなくなるかもしれません。

  • 絶対的な保証ではありません。通常、constが参照を保護するだけで、何らかの理由で基礎となる値を保護できない場合があります。 Cでも、constが到達できないEdgeケースがあり、constが提供する約束が弱められます。

  • 一般に、業界のセンチメントは強力なコンパイル時の保証から遠ざかっているように見えますが、どれほど快適であってもあなたと私にもたらされる可能性があります。したがって、午後には、const poisoningのために、コードベースの66%に触れることに費やします。 Python男は10の完全に機能し、十分に設計され、十分にテストされ、完全に機能しているPythonモジュールです。そして、ハッキングすらしていませんでした。 。

おそらく問題は、あなたがあなたの気の利いた新しい言語の採用を得ようとしているときに、一部の専門家でさえ曖昧な潜在的に論争の的となる機能を引き継ぐのはなぜですか?

編集:短い答え、新しい言語は採用のために登るのに険しい丘を持っています。デザイナーは、採用するために必要な機能について真剣に考える必要があります。たとえば、囲碁を取ってください。 Googleは、コナンバーバリアンスタイルのデザインを選択することで、最も深い宗教的な戦いのいくつかを残酷に打ち切りました。実際、私が見たものから、言語はその方が適していると思います。

7
Rob

言語にconstを追加することには、いくつかの哲学的問題があります。クラスにconstを宣言すると、クラスは変更できなくなります。ただし、クラスはメソッド(またはミューテーター)と結合された変数のセットです。クラスの状態を一連のメソッドの背後に隠すことで抽象化を実現します。クラスが状態を非表示にするように設計されている場合、その状態を外部から変更するためのミューテーターが必要であり、それはもうconstではありません。したがって、constを不変のクラスに宣言することのみが可能です。したがって、constは、クラス(またはconstを宣言する型)が簡単なシナリオでのみ可能と思われます...

とにかくconstが必要ですか?私はそうは思いません。デザインが良ければ、constがなくても簡単にできると思います。どのデータがどこに必要か、どのメソッドがデータ間メソッドであるか、どの抽象化がI/O、ネットワーク、ビューなどに必要か。その後、状態を処理するモジュールとクラスが自然に分割され、メソッドと状態を必要としない不変のクラス。

ほとんどの問題は、それ自体を保存、変換、描画できる大きな脂肪のデータオブジェクトで発生し、それをレンダラーなどに渡したいと思います。そのため、ビッグデータオブジェクトには高すぎるため、データの内容をコピーすることはできません。しかし、どちらも変更したくないので、constのようなものが必要です。コンパイラーに設計上の欠陥を見つけさせます。ただし、これらのオブジェクトを不変のデータオブジェクトのみに分割し、メソッドを担当モジュールに実装すると、不変を保証しながら、ポインターを(のみ)渡して、データに対して実行したいことを実行できます。

C++では、一部のメソッドをconstと宣言し、他のメソッドはミューテーターであるため、宣言しないことが可能であることを知っています。そして、しばらくしてからキャッシュが必要になり、getterがオブジェクトを変更し(遅延読み込みのため)、もうconstではありません。しかし、それがこの抽象化の要点でしたね?各呼び出しでどの状態が変化するかはわかりません。

0
Waster