私は直交性の概念を知っていますが、プログラミング言語の観点から、それを検証/証明する方法はありますか?
たとえば、C#では、メソッドのシグネチャとして、publicまたはstaticメソッドシグネチャを使用できます。どちらか一方または両方を使用でき、それらは互いに干渉しないので、互いに直交していますよね?
私の質問は、残りの機能、特に互いに関連しない機能についてはどうすればよいですか?
すべての機能が共存/スタックする必要がありますか?
100%直交するプログラミング言語はありますか?
私は直交性の概念を知っていますが、プログラミング言語の観点から、それを検証/証明する方法はありますか?
たとえば、C#では、メソッドのシグネチャとして、publicまたはstaticメソッドシグネチャを使用できます。どちらか一方または両方を使用でき、それらは互いに干渉しないので、互いに直交していますよね?
私の質問は、残りの機能、特に互いに関連しない機能についてはどうすればよいですか?
すべての機能が共存/スタックする必要がありますか?
100%直交するプログラミング言語はありますか?
回答:
C#のような汎用の高次言語の場合、直交性は「操作」と「オペランド」の区別を必要とするため、直交性が有用または有効なメトリックとして機能するかどうかはわかりません。 C#のような高次言語で区別できます。
直交性についての私の理解は、特定のCPUまたはマイクロコントローラーの命令セットの直交性が、データタイプに応じてこのCPUまたはコントローラーによって実行される操作に制約があるかどうかを示すアセンブラー言語に基づいています。初期の段階では、すべてのCPUが小数や長さの異なる数値などの操作をサポートしているわけではないため、これは重要でした。
この点で、C#自体ではなく、C#コンパイラのターゲットとしてスタックマシン言語を使用して、共通中間言語の直交性をチェックします。
C#の直交性に本当に興味があり、私がここで誤解されていない場合は(何であれ)、いくつかの遺伝的プログラミングアルゴリズムに目を向けることをお勧めします。それらを使用して、指定されたキーワードのセット(意味のないものも含む)からさまざまなプログラムを生成でき、それらがコンパイル可能かどうかを自動的にチェックできます。これにより、言語のどの要素を組み合わせることができるかを自動的に確認し、直交性メトリックのいくつかの側面を導き出すことができます。
「直交性」という用語は、正確な数学的概念を表す素人の用語です。言語用語は初期代数を形成します(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でさえそうではありません。ただし、多くの優れた言語は「直交特徴ベースにかなり近い」と判断することができます。これは、構文と基礎となるセマンティクスの両方に適用される言語に適した推奨事項です。
int (*intintfunc())(int) { ... }。intintfuncは、引数を取らず、1つのint引数を取り、int値を返す関数へのポインターを返す関数です。
直交性を証明することはネガティブを証明することです。これは、直交していない構成要素がないことを意味します。つまり、直交していないものがあることを証明する方がはるかに簡単です。
実際には、ほとんどの人は完全に直交しているかどうかではなく、度数の観点からプログラミング言語の直交性について話します。あるコンテキストで何かをすることからの知識が別のコンテキストに変換され、「期待通りのことをする」とき、その言語はより直交的であると言われます。すべてがリストであるため、LISPは高度に直交していると見なされますが、使いやすくするためにいくつかの冗長性があるため、100%直交しているとは言えません。C ++はあまり直交していないと見なされています。これは、思ったとおりに機能しない小さな「問題」がたくさんあるためです。
警告、私はこのトピックについて何も知りません。
ウィキペディアをざっと見ると、直交性は主に設計パターンとシステム設計に向けられていることがわかります。プログラミング言語の観点から、このエントリは、可能なアクションごとに1つだけの命令がある場合、または命令が他の命令と重複しない場合、命令セットが直交していることを示しています。
C#の場合、直交していると思います。ほとんどの構文トリック(foreach頭に浮かぶ)は、基本構造の特別に形成されたバージョン(ループにforeachなるfor)の単なるフロントエンドです。全体として、構文糖質がそれらを行うための追加の方法を提供しているとしても、言語は本当に単一の方法で物事を行うことをサポートするだけです。そして最後に、それはすべてMSIL(または最近でMSILは何と呼ばれていても)にコンパイルされ、おそらく直交しています。
構文上の砂糖の要素が本質的に「難しい方法」を実行するための「ラッパー」であるという注意を払えば、砂糖を省略して言語のさまざまな機能を分析し、本当に重複する構成要素があるかどうかを確認できます。そうでなければ、私はあなたが言語を直交的に宣言することができると思います。
私の2セント。
do...whileと同じ効果を提供するために使用することはできませんforか?どちらも構文糖と見なされているとは聞いたことがありません。
do whileは、単一のループの実行を保証し、事後の状態をチェックします。for最初に条件をチェックし、単一の実行を保証しません。
私の質問は、残りの機能、特に互いに関連しない機能についてはどうすればよいですか?
自分がやっていることを続け、機能するか禁止されているすべての組み合わせを列挙します。
それで全部です。それを行うのは非常に困難です。
すべての機能が共存/スタックする必要がありますか?
すべての機能が互いに干渉しない互いに素なサブセットに分割できる場合、確かに、すべてが賢明です。
すべてのデータ構造は、すべてのプリミティブ型で機能します。すべての式演算子はすべてのタイプで機能します。これらは直交性の一般的な定義です。しかし、あなたはもっと(またはもっと)欲しくなるかもしれません
ただし、オペレーティングシステムやレガシーライブラリが直交していないために、特殊なケースが発生する場合があります。
また、一部のタイプはまったく適合しません。たとえば、Pythonでは「順序付け」のために2つのディクショナリオブジェクトを比較できます。しかし、辞書間の「順序付け」の賢明な定義はほとんどありません。Pythonが定義していますが、かなり議論の余地があります。その特殊なケースでは、辞書が直交性テストに失敗しますか?
「十分に直交」とはどの程度直交ですか?あなたの言語の直交性の程度に満足するために何を見る必要がありますか?
非直交機能のリストは、ほとんどのプログラミング言語で実際に長いです。
私の頭に浮かぶのはほんの一部ですが、他にもたくさんあり、他の言語でもあります。
言語機能の間に微妙な干渉がないことを確認することは困難です。CAR Hoareが彼の論文「プログラミング言語設計のヒント」で示しているように、
言語設計の一部はイノベーションで構成されています。このアクティビティは、孤立した新しい言語機能につながります。言語設計の最も難しい部分は統合にあります。限られた言語機能のセットを選択し、結果が粗くならない一貫した単純なフレームワークになるまでそれらを磨きます。
おそらく、直交性を高めるための良い動きは、概念を統一することです(これは@ karl-bielfeldの回答の方向に進みます)。リストやオブジェクトなど、すべてが一致している場合は、競合が少なくなる可能性があります。または、後でクラスをネストする代わりに、コア機能にする。
ほとんどのプログラミング言語の論文では、形式化された言語のサブセット(「コア」)で言語の特定のプロパティ(型の健全性など)を証明しています。ここでは、反対のことを行い、すべての機能が安全に構成されていることを証明する必要があります。また、それは、「構成」することの意味を定義する必要があることを意味します。「走る」という意味ですか?(この場合、動的および静的型付けのエッジケースに関する上記のリンクは安全です)。「安全」という意味ですか?開発者の観点から予測可能であることを意味しますか?
これらすべては非常に興味深いものですが、非常にやりがいがあります。