web-dev-qa-db-ja.com

プログラミング言語の直交性を検証/証明する方法は?

私は直交性の概念を知っていますが、プログラミング言語の観点から、それを検証/証明する方法はありますか?

たとえばC#では、メソッドシグネチャにpublicまたはstaticを使用できます。どちらか一方または両方を使用でき、それらは互いに干渉しないので、それらは互いに直交していますよね?

私の質問は、残りの機能、特に相互に関連しない機能についてはどうすればよいですか?

すべての機能が共存/スタックする必要がありますか?

100%直交するプログラミング言語はありますか?

10
Joan Venge

C#のような汎用の高次言語の場合、直交性は「操作」と「オペランド」の区別が必要なため、直交性が有用または有効なメトリックとして機能するかどうかはわかりません。 C#のような高次言語で区別できます。

直交性についての私の理解は、特定のCPUまたはマイクロコントローラーの 命令セットの直交性 がデータ型に応じてこのCPUまたはコントローラーによって実行される操作にいくつかの制約があるかどうかを示すアセンブラー言語に基づいています。初期の段階では、すべてのCPUが小数や異なる長さの数などの演算をサポートしているわけではないため、これは重要でした。

この点で、C#自体ではなく、C#コンパイラのターゲットとしてスタックマシン言語を使用して、 Common Intermediate Language の直交性をチェックします。

C#の直交性に本当に興味があり、私がここで誤解されていない場合は(なんらかの目的で)、いくつかの 遺伝的プログラミングアルゴリズム に目を向けることをお勧めします。それらを使用して、指定されたキーワードのセット(意味のないものも含む)からさまざまなプログラムを生成し、それらがコンパイル可能かどうかを自動的にチェックできます。これにより、言語のどの要素を組み合わせることができるかを自動的に確認し、直交性メトリックのいくつかの側面を導き出すことができます。

4

「直交性」という用語は、正確な数学的概念を表す素人の用語です。言語用語は最初の代数を形成します(Wikipediaで調べてください)。

それは基本的に「構文と意味の間に1-1の対応がある」ことを意味します。つまり、物事を表現する方法は1つしかなく、特定の場所に表現を置くことができれば、そこに他の表現を置くこともできます。

「直交」について考えるもう1つの方法は、構文が置換の原則に従うことです。たとえば、式のスロットを持つステートメントがある場合、any式をそこに置くことができ、結果は依然として構文的に有効なプログラムです。さらに、交換すると

「意味」は計算結果を意味するものではないことを強調したい。明らかに、1 + 2と2 + 1は両方とも3に等しくなります。ただし、項は異なり、同じ結果になっても異なる計算を意味します。 2つのソートアルゴリズムが異なるように、意味も異なります。

「抽象構文木」(AST)を聞いたことがあるかもしれません。ここで「抽象的」という言葉は、正確に「直交」を意味します。技術的には、ほとんどのASTは実際には抽象的ではありません!

おそらく「C」プログラミング言語を聞いたことがありますか? C型表記は抽象的ではありません。検討してください:

int f(int);

したがって、ここに型宣言intを返す関数宣言があります。この関数へのポインターのタイプは、次のように指定されます。

int (*)(int)

関数の型を書くことはできません! C型表記は大したことを吸う!それは抽象的なものではありません。それは直交していません。ここで、intの代わりに上記の型を受け入れる関数を作成するとします。

int (*) ( int (*)(int) )

すべて大丈夫ですが、代わりにそれを返したい場合はどうしますか。

int (*)(int) (*) (int)

おっと!無効。括弧を追加しましょう:

(int (*)(int)) (*) (int)

おっと!それも機能しません。これを行う必要があります(それが唯一の方法です!):

typedef int (intintfunc*) (int);
intintfunc (*)(int)

これで問題ありませんが、ここでtypedefを使用する必要があります。 Cは吸う。それは抽象的なものではありません。それは直交していません。 MLでこれを行う方法は次のとおりです。

 int -> (int -> int)

構文レベルでCを非難します。

では、C++をflogしてみましょう。上記の愚かさをテンプレートで修正し、(多かれ少なかれ)表記のようなMLを取得できます。

fun<int, int>
fun< fun<int,int>, int>

しかし、実際の型システムには、参照による根本的な欠陥があります。Tが型の場合、T&タイプ?答えは気まぐれです。構文レベルでは、タイプU = T&がある場合、U&は許可されますが、それはT&を意味するだけです。参照への参照は元の参照です。これは最悪だ!それは意味的に一意性要件を破ります。さらに悪いことに、T&&は構文的には許可されていません。これは置換の原則に違反します。したがって、C++参照は、バインディング時間(解析または型分析)に応じて、2つの異なる方法で直交性を壊します。これを正しく行う方法を理解したい場合は、ポインタに問題はありません。

直交する実際の言語はほとんどありません。表現の明快さを装うSchemeでさえそうではありません。ただし、多くの優れた言語は「直交特徴ベースにかなり近い」と判断することができます。これは、構文と基礎となるセマンティクスの両方に適用される言語に適した推奨事項です。

6
Yttrill

直交性を証明することはネガティブを証明することです。これは、直交しない構成要素がないことを意味します。つまり、何かを証明する方がはるかに簡単ですではない直交よりも直交します。

実際には、ほとんどの人はプログラミング言語の直交性について、完全に直交しているかどうかではなく、度数の観点から話します。あるコンテキストで何かをすることによる知識が別のコンテキストに変換され、「期待通りのことをする」とき、その言語はより直交していると言われます。 すべてがリストであるため、LISPは高度に直交していると見なされますが、使いやすくするためにいくつかの冗長性があるため、100%直交しているとは言えません。 C++はあまり直交していないと見なされています。これは、思ったとおりに機能しない小さな「落とし穴」がたくさんあるためです。

4
Karl Bielefeldt

警告、このトピックについては何も知りません。

ウィキペディアをざっと見ると、直交性は主に設計パターンとシステム設計に向けられていることがわかります。プログラミング言語に関しては、このエントリは、可能なアクションごとに1つだけの命令がある場合、または命令が他の命令と重複しない場合、命令セットが直交していることを示しています。

ほとんどの構文トリック(foreachが頭に浮かぶ)は、基本構造の特別に形成されたバージョンのフロントエンドにすぎない(foreachforループになる)という点で、C#の場合は直交していると思います。全体として、構文糖質がそれらを行うための追加の方法を提供しているとしても、言語は物事を単一の方法で行うことを本当にサポートしているだけです。そして最後に、すべてがMSIL(または最近では何と呼ばれていても)にコンパイルされ、MSILはおそらく直交しています。

構文上の砂糖の要素が本質的に「難しい方法」を実行するための「ラッパー」であるという注意を払えば、砂糖を省略して言語のさまざまな機能を分析し、本当に重複する構成要素があるかどうかを確認できます。そうでなければ、私はあなたが言語を直交と宣言することができると想像します。

私の2セント。

3
digitlworld

私の質問は、残りの機能、特に互いに関連しない機能についてはどうすればよいですか?

自分がやっていることを続け、機能するか禁止されているすべての組み合わせを列挙します。

それで全部です。それを行うのは非常に困難です。

すべての機能が共存/スタックする必要がありますか?

all機能が互いに干渉しない互いに素なサブセットに分割できる場合、確かにallが賢明です。

すべてのデータ構造は、すべてのプリミティブ型で機能します。すべての式演算子はすべてのタイプで機能します。これらは直交性の一般的な定義です。しかし、あなたはもっと(またはもっと)欲しくなるかもしれません

ただし、オペレーティングシステムやレガシーライブラリが直交していないために、特殊なケースが発生する場合があります。

また、一部のタイプはまったく適合しません。たとえば、Pythonを使用すると、2つのディクショナリオブジェクトを比較して「順序付け」を行うことができます。しかし、辞書間の「順序付け」の意味のある定義はほとんどありません。Python特殊なケースで辞書が直交性テストに失敗するのでしょうか?

「十分に直交」とはどの程度直交か?何をするあなたあなたの言語の直交性の程度に満足するために見る必要があります。

2
S.Lott

非直交機能のリストは、ほとんどのプログラミング言語で実際に長くなっています。

  • 匿名クラスはJavaリフレクションと競合します
  • ジェネリックと型消去がJavaリフレクションと競合します
  • 配列はオブジェクトですが、特殊なタイプであるため、他のオブジェクトとは多少異なります。
  • 静的メソッドとインスタンスメソッドは同じではありません。静的メソッドをオーバーライドすることはできません
  • ネストされたクラスは後から考える
  • メッセージディスパッチ戦略に対する動的型付けと静的型付けの影響(例:this Edge case in C#を参照)
  • 等.

私の頭に浮かぶのはほんの一部ですが、他にもたくさんあり、他の言語でもあります。

言語機能間に微妙な干渉がないことを確認することは困難です。 C.A.R.としてHoareは彼の論文「プログラミング言語設計のヒント」で次のように述べています。

言語設計の一部はイノベーションで構成されています。このアクティビティは、孤立した新しい言語機能につながります。言語設計の最も難しい部分はintegrationにあります。限られた言語機能のセットを選択し、結果が一貫した単純なフレームワークになるまでそれらを磨きます。より粗いエッジ。

おそらく、直交性を高めるための良い動きは、概念を統一することです(これは@ karl-bielfeldの回答の方向に進みます)。リストやオブジェクトなど、すべてが一致している場合は、競合が少なくなる可能性があります。または、後でクラスをネストする代わりに、コア機能にする。

ほとんどのプログラミング言語の論文では、形式化された言語のサブセット(「コア」)で言語の特定のプロパティ(型の健全性など)を証明しています。ここでは、反対のことを行い、すべての機能が安全に構成されていることを証明する必要があります。また、それは、「構成」することの意味を定義する必要があることを意味します。 「走る」という意味ですか? (この場合、動的および静的型付けのEdgeケースに関する上記のリンクは安全です)。 「安全」という意味ですか?開発者の観点から予測可能であることを意味しますか?

これらすべては非常に興味深いものですが、非常にやりがいがあります。

2
ewernli