25


11

C#でかなり高度なことをしようとすると(ある種のハックのように)、「ファーストクラス」の概念が提起されます。

例えば、メソッドはxyzを使うことができるので(xyzはそのメソッドがするものではありませんが、一般的にメソッドがあなたに与えるものです、私はxyzが今何であったか覚えていません) NET 1.1のデリゲートは、ファーストクラスのプログラミング構成要素ではないため、メソッドに渡すことができませんでした(これらの行に沿って何かを読みます)。

ファーストクラスのプログラミング構成とは何ですか?

ありがとう

6 Answer


38


プログラミング言語における "first-class citizen "または" first-class element "の概念は、イギリスのコンピュータ科学者http://Wikipedia.Org/によって導入されました。ウィキ/ Christopher_Strachey [Christopher Strachey] 1960年代の第一級関数の文脈で。 この原則の最も有名な定式化は、おそらくGerald Jay Sussmanによる コンピュータプログラムの構造と解釈にあります。ハリーアベルソン:

  • それらは変数によって命名されるかもしれません。

  • それらは手続きへの引数として渡すことができます。

  • 手続きの結果として返されることがあります。

  • それらはデータ構造に含まれるかもしれません。

基本的に、それはあなたがプログラミング言語の他のすべての要素でできることすべてがこのプログラミング言語の要素でできることを意味します。


22


I suspect you won’t find a formal definition https://stackoverflow.com/a/646862/22656 [明らかにJörgW Mittagが見つけた] :)

その正式な定義を考えると、私の答えの残りの部分は単にその時の私の理解です。 「一流の構文」という用語を使う人がまったく同じことを意味するかどうかは、もちろん別の問題です。

何かが「ファーストクラス」の構成要素であるかどうかを判断する方法は、次のように自分自身に尋ねることです。

_ この機能はサポートされており、言語の他の部分と完全に統合されていますか、それとも「ボルトで締められた」という印象を与える不必要な制限が多くあります。より完全に「言語の一部」であった場合、本当に役立つでしょうか? _

ご覧のとおり、これは明確なグレーの領域です:)

実際のところ、C#のデリゲートはその好例です。 C#1では、デリゲートをメソッドに渡すことができ、それらが言語にうまく統合される方法はたくさんありました(変換の利用、イベント処理、=および - = Delegate.Combine / Removeへの変換など)。 私は彼らがファーストクラスの構成要素を持っていたと思います。 ただし、これは、匿名メソッド、暗黙的なメソッドグループ変換、ラムダ式、および共分散によって、C#2および3からデリゲートが非常に高い評価を得ているという事実と矛盾しません。 彼らは今や間違いなくファーストクラスの構成要素である…​ C#1では「ファーストクラス」だと言っても、誰かが賛成できない理由がわかります。

同様のケースが、 + IEnumerable +`に対して行われる可能性があります。 C#1.0では、これは `+ foreach +`によってサポートされていましたが、 `+ foreach +`ループは最後に `+ IEnumerator +`を破棄しませんでした。 この部分はC#1.2で修正されましたが、作成するのではなく_consuming_ `+ IEnumerable + sの言語サポートのみが残っていました。 C#2.0にはイテレータブロックが用意されていたため、 + IEnumerable +(およびその一般的な同等物)を簡単に実装できました。 それは、反復可能なシーケンスの概念がC#1.0の「ファーストクラス」の構成要素ではなかったことを意味しますか? 議論の余地がある、基本的に…​


7


_ ファーストクラスのプログラミング構成とは何ですか? _

言語が他の種類のオブジェクトに似た方法で*サポートしている場合、何かは第一級の構成要素です。

たとえば、Cでは、関数は第一級の構成要素とは見なされません。実行時に他の種類のオブジェクトを作成できますが、新しい関数をインスタンス化することはできません。 これとは対照的に、C#3以降では、ラムダ/無名関数の導入により、関数はおそらく第一級の構成要素と見なされます。

他の多くのものと同様に、これは当然主観的な定義です。 より具体的な例については、http://c2.com/cgi/wiki?FirstClass[C2]と同様に、Wikipediaにhttp://en.wikipedia.org/wiki/First-class_object [良い要約]があります。


1


http://c2.com/cgi/wiki?FirstClass[C2 wiki]にはファーストクラスの言語構成要素に関する優れた記事があります。]基本的に、言語の中で偽造する必要はないということです。


1


私が一流のプログラミング構成を理解しているということは、可能な限り最善の方法で_何か_を実行できること、または2つまたは3つの他の概念を組み合わせる必要がないことです。

だから、Javaは一流のクロージャサポートを持っていません。 ただし、クロージャを使用するほとんどすべてのものをサポートするクラスを(別の概念を使用して)構築してからそのクラスのインスタンスを作成する(another concept)か、そのクラスを匿名で拡張する(yet another concept)ことでやや偽ります。

'functions’と同じです。 Javaでは関数を持つことはできませんが、静的メソッドを持つことはできますが、それは似ていますがそれでも概念は異なります。

ある人(私ではありません)は、Javaの総称サポートはファーストクラスではないと主張することもできます。これは、ライブラリーのハックであり、実際には言語に「入って」いないからです。 つまり、C#で総称を使ってできることのいくつかはJavaではできないということです。


1


ファーストクラスのプログラミング構成要素とは何ですか?

簡単な答え:それは言語が提供するすべての標準操作をサポートするものです。 オブジェクト指向言語では、最初のクラス構成要素は、ご想像のとおり、オブジェクトです。 そのような言語では、効率上またはレガシー上の理由から、セカンドクラスの市民、通常はプリミティブデータ型は適切なオブジェクトではないため、特定のことができないことがよくあります。

たとえば、JavaではPointは本格的なオブジェクトです。 あなたは宣言することができます

+ List plist; +

それからそれにポイントを入れなさい。 intは本格的なオブジェクトではありません。 あなたがそれからint - サブクラスを使ってすることができない、またはいくつかの事前定義された演算子の他にそれの上でメソッドを呼び出すことができないある特定の事があります。 また、あなたはそれを

+ List intlist; +

Javaはこの問題を解決し、本格的なオブジェクトである「箱入り」タイプのIntegerがあります。 たとえば、 `+ List +`を宣言できます。 ただし、整数を使用すると、「int」を使用するよりもはるかに効率が悪くなります。 Javaは、どちらか一方が必要な状況で、整数型の自動ボックス化およびボックス化解除(つまり、変換)をintに戻したり、戻したりして、両方の長所を組み合わせることを支援します。

整数に2つの型 - 整数と整数 - を持つことは混乱を招くもので、ハックのようなものです。 私は、Javaの初期のバージョンにはプリミティブがなく、そのすべての型が本格的なオブジェクトであったと言います。 これは意図した用途には遅すぎることが判明しました(もちろん初期のJavaはとにかく遅くなることがわかった!)ので、適切なオブジェクトセマンティクスをサポートしないいくつかのプリミティブが追加されました。

NET 1.1のデリゲートは、ファーストクラスのプログラミング構成要素ではないため、メソッドに渡すことができませんでした(これらの行に沿って何かを読んでいます)。

私は.NETについて何も知りませんが、あなたがその考えを持っているように思えます。 そうです、他の標準オブジェクトのようにデリゲートをメソッドに渡すことができないのであれば、それらはファーストクラスのプログラミング構成要素ではありません。