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


10

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

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

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

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

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


(ほぼ)最初から始める:アセンブリ言語?
Matthew Flynn、2012年

1
実際に何かを証明するには、正式な定義が必要です。また、定義がC#仕様と同じくらいの大きさになる場合、何かを証明するには多くの作業が必要になります。
1

回答:


4

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

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

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

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


6

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

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

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

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

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

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

int f(int);

したがって、ここにtypeを返す関数宣言があります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でさえそうではありません。ただし、多くの優れた言語は「直交特徴ベースにかなり近い」と判断することができます。これは、構文と基礎となるセマンティクスの両方に適用される言語に適した推奨事項です。


MLは他のMLより直交していると思いますか?LispとHaskellはどうですか?
Joan Venge、2012年

1
@joan:まあ、lispには機能がないので、vaccuuoの要件を満たします:)
Yttrill

@joan:私はHaskellプログラマではないので、少し難しいですが、Haskellでの「非常に高いレベルの機能」の存在は、強い直交性を示しています。MonadsまたはArrowsの一貫した実装はあり得ません。言語の残りの部分には実質的な「直交性」がある
イットリル2012年

あなたがパスカルについてどう思うか。Cよりもロードが良いようです
スーパーキャット2015年

私のコメントはほぼ4年遅れていることは知っていますが、たまたま見つけました。この答えは、すべてについて間違っています。全体でも「それが唯一の方法です!」一部は単に間違っています。typedefの例がなくても、簡単にそれを表現できますint (*intintfunc())(int) { ... }。intintfuncは、引数を取らず、1つのint引数を取り、int値を返す関数へのポインターを返す関数です。
Wiz 2016

4

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

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


3

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

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

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

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

私の2セント。


forとforeachの両方が言語の機能であり、一方が他方の構文糖質である場合(foreachの効果はforを使用して達成できる場合)、言語はその直交性を失います。
vpit3833

do...whileと同じ効果を提供するために使用することはできませんforか?どちらも構文糖と見なされているとは聞いたことがありません。
マシューフリン

1
@MatthewFlynn:Bah!これらはどちらも構文上の砂糖です。反復を再帰的な関数に置き換えることができます。;)
FrustratedWithFormsDesigner 2012年

2
@FrustratedWithFormsDesigner:それはGOTOの単なる構文糖ではありませんか?
Ivan

2
@MatthewFlynn do whileは、単一のループの実行を保証し、事後の状態をチェックします。for最初に条件をチェックし、単一の実行を保証しません。
digitlworld 2012年

2

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

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

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

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

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

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

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

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

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


2

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

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

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

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

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

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

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

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

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