タグ付けされた質問 「language-design」

プログラミング言語の設計と構造に関する質問。

2
なぜビット演算子は比較よりも優先度が低いのですか?
理由を説明してもらえますか、なぜ最も一般的な言語の束(下記の注を参照)で比較演算子(==、!=、<、>、<=、> =)がビットごとの演算子(&、|、^ 、〜)? この優先順位が自然な使用法に出会ったことはないと思います。それは常に次のようなものです: if( (x & MASK) == CORRECT ) ... // Chosen bits are in correct setting, rest unimportant if( (x ^ x_prev) == SET ) // only, and exactly SET bit changed if( (x & REQUIRED) < REQUIRED ) // Not all conditions satisfied 私が使用する場合: flags = …

6
Javaとは異なり、「new」および「virtual + override」キーワードでC#が作成されたのはなぜですか?
Javaではノーがあるvirtual、new、overrideメソッド定義のキーワード。したがって、メソッドの動作は理解しやすいです。場合原因DerivedClassが延びBaseClassのを、同じ名前と同じシグネチャを持つ方法有するBaseClassのその後ランタイム多形で行われるオーバーライドが(メソッドではない提供しますstatic)。 BaseClass bcdc = new DerivedClass(); bcdc.doSomething() // will invoke DerivedClass's doSomething method. C#に来ると、非常に多くの混乱が発生し、newor virtual+deriveまたはnew + virtualオーバーライドがどのように機能するかを理解するのが難しくなります。 なぜ世界DerivedClassで同じ名前と同じシグネチャを持つメソッドを追加しBaseClass、新しい動作を定義するのかを理解することはできませんが、実行時のポリモーフィズムでは、BaseClassメソッドが呼び出されます!(これはオーバーライドではありませんが、論理的にはそうする必要があります)。 以下の場合にはvirtual + override論理的な実装が正しいですが、プログラマが、彼はコーディングの際に上書きするようにユーザーに権限を与えるべき方法だと思うしなければならないのに。これには賛否両論があります(今は行かないでください)。 それで、なぜC#には非論理的な推論と混乱のためのスペースがあるのか。それで、どの現実世界の文脈で、代わりに使用するか、またvirtual + override代わりに使用することを考えるべきかという質問を再構成できますか?newnewvirtual + override 特にOmarからの非常に良い回答の後に、C#デザイナーはメソッドを作成する前にプログラマが考える必要があることについてより多くのストレスを与えたと思います。 今、私は質問を念頭に置いています。Javaのように、次のようなコードがあった場合 Vehicle vehicle = new Car(); vehicle.accelerate(); 後で新しいクラスをSpaceShip派生させVehicleます。次にcar、すべてをSpaceShipオブジェクトに変更したいので、1行のコードを変更するだけです Vehicle vehicle = new SpaceShip(); vehicle.accelerate(); これは、コードのどのポイントでも私のロジックを壊しません。 しかし、C#の場合、if SpaceShipがVehicleクラスをオーバーライドせずにaccelerate使用するnewと、コードのロジックが壊れます。それは不利ではないですか?

9
言語に論理演算子としての含意が含まれないのはなぜですか?
奇妙な質問かもしれませんが、なぜ多くの言語(Java、C、C ++、Python Haskell-最後のユーザー定義演算子はそれを追加するのは簡単ですが)で論理演算子としての意味がないのですか?論理的含意を書くと(特にアサートまたはアサートのような式で)否定するか、またはORを使用して否定する方がはるかに明確です。 encrypt(buf, key, mode, iv = null) { assert (mode != ECB --> iv != null); assert (mode == ECB || iv != null); assert (implies(mode != ECB, iv != null)); // User-defined function }

4
なぜ最近のプログラミング言語で変数名の後に型が続くのですか?
ほぼすべての最新のプログラミング言語(Go、Rust、Kotlin、Swift、Scala、Nim、Pythonの最終バージョンでも)で、型が常に変数宣言の変数名の後に来るのはなぜですか? なぜx: int = 42ありませんかint x = 42? 後者は前者よりも読みにくいですか? それは単なるトレンドですか、このソリューションの背後には本当に意味のある理由がありますか?

2
C#で「void」がジェネリック型として許可されないのはなぜですか
void構築可能でなく、ジェネリック型として許可されないことを支持して設計上の決定は何でしたか?結局それだけで特別な空であるstructと明確な持つの合計PITA避けているだろうFuncし、Actionデリゲートを。 (C ++は明示的なvoid戻り値を許可voidし、テンプレートパラメータとして許可します)

3
型システムとは何ですか?
バックグラウンド 私はサイドプロジェクトとして言語を設計しています。動作するアセンブラー、静的アナライザー、それに仮想マシンがあります。構築したインフラストラクチャを使用して、重要なプログラムを既にコンパイルおよび実行できるため、大学でプレゼンテーションを行うことを考えました。 私の話の中で、私はVMが型システムを提供することについて言及しました、「あなたの型システムは何のためにあるのですか?」答えた後、私は質問をする人に笑われました。 したがって、この質問をすることで評判を失うことはほぼ確実ですが、プログラマーに頼ります。 私の理解 私が理解しているように、型システムはプログラム内のエンティティに関する追加情報の層を提供するために使用されるため、ランタイム、コンパイラー、またはその他の機械は、操作対象のビット文字列をどう処理するかを認識します。また、コントラクトの維持にも役立ちます。コンパイラ(またはコードアナライザー、ランタイム、またはその他のプログラム)は、プログラマーが期待する値でプログラムが動作することをいつでも検証できます。 タイプは、それらの人間のプログラマーに情報を提供するためにも使用できます。たとえば、次の宣言を見つけます。 function sqrt(double n) -> double; これよりも便利 sqrt(n) 前者は多くの情報を提供します:sqrt識別子は関数であり、double入力として単一のものを取り、double出力として別のものを生成します。後者は、おそらく単一のパラメーターを取る関数であることを示しています。 私の答え それで、「あなたのタイプシステムは何のためですか?」私は次のように答えました: 型システムは動的です(型は値を保持する変数ではなく値に割り当てられます)が、意外な強制ルールがなければ強力です(互換性のない型を表すため、文字列を整数に追加できませんが、浮動小数点数に整数を追加できます) 。 タイプシステムは、命令のオペランドが有効であることを確認するためにVMによって使用されます。また、プログラマーは、関数に渡されたパラメーターが有効(つまり、正しい型)であることを確認するために使用できます。 型システムは、サブタイピングと多重継承をサポートしています(プログラマーは両方の機能を使用できます)。オブジェクトのメソッドの動的ディスパッチが使用される場合、型は考慮されます。 次の質問は、「タイプは値にどのように割り当てられますか?」でした。そこで、すべての値がボックス化され、タイプの名前、応答するメッセージ、および継承するタイプに関する情報を提供するタイプ定義構造を指すポインターがあることを説明しました。 その後、私は笑われ、「それは本当のタイプシステムではない」というコメントで私の答えは却下されました。 だから-私が説明したものが「実際のタイプシステム」として適格でない場合、どうなりますか?その人は、私が提供するものを型システムと見なすことができないということは正しいのですか?

5
すべての<algorithm>関数がコンテナーではなく範囲のみを取得するのはなぜですか?
には多くの便利な関数がありますが&lt;algorithm&gt;、それらはすべて「シーケンス」、つまりイテレータのペアで動作します。たとえば、コンテナがあり、そのstd::accumulate上で実行したい場合、次のように書く必要があります。 std::vector&lt;int&gt; myContainer = ...; int sum = std::accumulate(myContainer.begin(), myContainer.end(), 0); 私がやろうとしているのは: int sum = std::accumulate(myContainer, 0); 私の目では、これはもう少し読みやすく、はっきりしています。 コンテナの一部のみを操作したい場合があるかもしれないので、範囲を渡すオプションがあることは間違いなく便利です。しかし、少なくとも私の経験では、それはまれな特別なケースです。私は通常、コンテナ全体を操作したいと思うでしょう。 これは、コンテナとのコールを取るラッパー関数書くのは簡単だbegin()し、end()その上に、このような便利な機能が標準ライブラリに含まれていません。 このSTL設計の選択の背後にある理由を知りたい。

4
Pythonのイテレータが例外を発生させるのはなぜですか?
Javaの反復子の構文は次のとおりです(C#の構文に似ています)。 Iterator it = sequence.iterator(); while (it.hasNext()) { System.out.println(it.next()); } 理にかなっています。Pythonの同等の構文は次のとおりです。 it = iter(sequence) while True: try: value = it.next() except StopIteration: break print(value) 例外は、例外的な状況でのみ使用されることになっていると思いました。 Pythonが例外を使用して反復を停止するのはなぜですか?

8
例外処理メカニズムなしで現代言語を設計する理由
多くの現代言語は豊富な例外処理機能を提供していますが、AppleのSwiftプログラミング言語は例外処理メカニズムを提供していません。 私は例外に悩まされていますが、これが何を意味するのかを頭で悩ませています。Swiftにはアサーションがあり、もちろん戻り値があります。しかし、私は例外に基づいた考え方が例外なく世界にどのようにマップされるのかを想像するのに苦労しています(そのため、そのような世界が望ましい理由)。Swiftのような言語ではできないことはありますか?例外をなくすことで何かを得られますか? たとえば、次のように表現するにはどうすればよいでしょうか try: operation_that_can_throw_ioerror() except IOError: handle_the_exception_somehow() else: # we don't want to catch the IOError if it's raised another_operation_that_can_throw_ioerror() finally: something_we_always_need_to_do() 例外処理のない言語(たとえば、Swift)で

13
割り当て演算子が左側に割り当てられるのはなぜですか?
私はちょうど友達プログラミングを教え始めました(Pythonを使用しています)。変数の作成と代入演算子について議論し始めたとき、彼女はなぜ右の値が左の名前に割り当てられているのかを尋ねました。 。 私にとってそれは自然に思えたので、あまり考えたことはありませんでしたが、彼女は左から右の方が自然であると言った、それが私たちのほとんどが自然言語を読む方法だからです。 私はそれについて考えて、割り当てられた名前(プログラマが再利用する必要がある)が簡単に表示され、左に揃えられているため、コードがはるかに読みやすくなると結論付けました。 aligned = 2 on = 'foo' + 'bar' + 'foobar' the = 5.0 / 2 left = 2 + 5 とは対照的に: 2 = aligned 'foo' + 'bar' + 'foobar' = on 5.0 / 2 = the 2 + 5 = right # What were the names …

5
古いプログラミング言語が引き続き改訂されるのはなぜですか?
この質問は、「なぜ人々はまだ古いプログラミング言語を使用しているのですか?」ではありません。私はそれをよく理解しています。実際、私が最もよく知っている2つのプログラミング言語はCとSchemeで、どちらも70年代に遡ります。 最近、C99とC11対C89の変更について読んでいました(実際にCの最も使用されているバージョンであり、K&Rから学んだバージョンです)。周りを見ると、頻繁に使用されるすべてのプログラミング言語は、少なくとも10年に1回程度新しい仕様を取得しているようです。Fortranを使用しているほとんどの人がまだFORTRAN 77を使用しているという事実にもかかわらず、Fortranでも新しいリビジョンを取得しています。 たとえば、組版システムTeXのアプローチと比較してください。1989年、TeX 3.0のリリースに伴い、Donald KnuthはTeXは機能が完全であり、将来のリリースにはバグ修正のみが含まれると宣言しました。これ以上に、彼は彼の死の際に、「残っているすべてのバグが機能になる」と述べており、それ以上の更新は一切行われないと述べています。他の人はTeXを自由にフォークして自由にフォークできますが、結果のシステムの名前が変更され、公式のTeXとは異なることを示します。これは、KnuthがTeXを完璧だと考えているからではなく、50年後に同じことをする安定した予測可能なシステムの価値を理解しているからです。 ほとんどのプログラミング言語デザイナーが同じ原則に従っていないのはなぜですか?もちろん、言語が比較的新しい場合、落ち着く前に急速な変化の期間を経ることは理にかなっています。また、既存の疑似標準を体系化するか、意図しない読み取り値を修正する以上の小さな変更に、実際に誰も反対することはできません。しかし、10、20年経ってもまだ言語の改善が必要なように思える場合、すでに使用されているものを変更しようとするのではなく、単にフォークするか、最初からやり直さないのですか?Fortranでオブジェクト指向プログラミングを本当にしたい人がいるなら、その目的のために「Objective Fortran」を作成し、Fortranをそのままにしてみませんか? 将来の改訂に関係なく、C89はすでに標準であり、人々がそれを使用し続けることを止めるものはないと言えるでしょう。これは一種の真実ですが、意味合いには結果があります。GCCは、pedanticモードで、C99で非推奨またはわずかに異なる意味を持つ構文について警告します。つまり、C89プログラマーは新しい標準を完全に無視することはできません。したがって、C99には、言語を使用するすべての人にこのオーバーヘッドを課すのに十分な利点がなければなりません。 これは本当の質問であり、議論を呼びかけるものではありません。明らかに私はこれについて意見を持っていますが、現時点では、これがすでに行われている方法だけではない理由を理解しようとしています。質問は次のとおりです。 古い言語に基づいて新しい言語を作成するのではなく、言語標準を更新することの(実際の、または認識されている)利点は何ですか?

4
構造体とクラスがC#で概念を分けているのはなぜですか?
C#でプログラミングしているときに、理解できない奇妙な言語設計の決定につまずきました。 したがって、C#(およびCLR)には2つの集約データ型があります:(struct値型、スタックに格納され、継承なし)およびclass(参照型、ヒープに格納され、継承あり)。 この設定は最初はいい感じに聞こえますが、その後、集計タイプのパラメーターを取るメソッドに出くわし、実際に値タイプか参照タイプかを判断するには、そのタイプの宣言を見つける必要があります。時には非常に混乱することがあります。 一般的に受け入れられている問題の解決策は、すべてstructのを「不変」(フィールドをに設定readonly)として宣言して、起こりうる間違いを防ぎ、structsの有用性を制限しているようです。 たとえば、C ++ははるかに使いやすいモデルを採用しています。スタックまたはヒープのいずれかにオブジェクトインスタンスを作成し、値または参照(またはポインター)で渡すことができます。私はC#がC ++に触発されたと聞き続けていますが、なぜこの1つの手法を採用しなかったのか理解できません。組み合わせるclassとstruct経由で参照として(明示的に)二つの異なる割り当てオプション(ヒープとスタック)と一方の構築物へと値として周りにそれらを渡したりrefしてout、キーワードはいいことのように思えます。 質問は、なぜやったclassし、structC#とCLRで別々の概念の代わりに、2つのアロケーションオプションを持つ1つの集約タイプになりますか?


15
言語はCPU設計にどのように影響しましたか?[閉まっている]
私たちはされていることが多い語ったが、これは真実ではない、ハードウェアは、プログラムがそれだけでコンパイルされたバイナリコードを見ているように書かれている言語を気にしないこと。たとえば、謙虚なZ80を考えてみましょう。8080命令セットへのその拡張には、C-スタイル(NULLで終了する)文字列をスキャンするのに役立つCPIRなどの命令が含まれますstrlen()。設計者は、Cプログラムの実行(文字列の長さがヘッダーにあるPascalとは対照的に)が、設計で使用される可能性が高いことを特定している必要があります。別の古典的な例は、Lisp Machineです。 他にどんな例がありますか?たとえば、特定のプロセッサが特定の言語の規則を好むようにする命令、レジスタの数とタイプ、アドレス指定モードはありますか?私は特に同じ家族の改訂に興味があります。

22
識別子の空白は慣用的なものですか?[閉まっている]
C#スタイルでは、識別子でCamelCaseを使用して単語を区切ることを推奨しています。Lispの伝統は、代わりにダッシュを使用することを提案しています。 識別子にスペースを使用することが許可されているだけでなく、複数単語の識別子を使用するときに一般的に使用されるイディオムがあるプログラミング言語が存在したことはありますか? 一部のScheme実装では、スペース付きの識別子を使用することは可能ですが、広く見られる慣行ではありません。以下に例を示します。 Petite Chez Scheme Version 8.4 Copyright (c) 1985-2011 Cadence Research Systems &gt; (define |hey there| 100) &gt; (define |x y z| 200) &gt; (list |hey there| |x y z|) (100 200)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.