ファーストクラス関数と高次関数の違い


129

私は思ったんだけどどうか/の間にどのような違いファーストクラスの機能高階関数

私はこれら2つのWikiページを読みましたが、どちらもかなり似ています。同じことを言っているのに、なぜ2つの用語が必要なのでしょうか。

グーグルを試してみましたが、有用なものは見つかりませんでした。

回答:


154

違いがあります。言語にファーストクラスの関数があると言うとき、それはその言語が関数を値として扱うことを意味します。つまり、関数を変数に割り当てたり、渡したりすることができます。高階関数は、他の関数で機能する関数です。 1つ以上の関数を引数として取り、関数を返すこともできます。

「高次」の概念は、数学的な意味の関数のように、関数全般に適用できます。「ファーストクラス」の概念は、プログラミング言語の関数とのみ関係があります。「ファーストクラスの関数」などの関数を参照するときはめったに使用されません。「ある言語はファーストクラスの関数をサポートしている/持っていない」と言う方がはるかに一般的です。

高次関数もサポートしないファーストクラスの関数を備えた言語や、逆に高次関数を備えたがファーストクラスの関数をサポートしていない言語を想像するのは難しいため、この2つは密接に関連しています。


2
私が混乱しやすいのは、それらが密接に関連しているということです。
Simon

63
@Simon混乱を避けるための鍵は、言語にファーストクラスの関数がある(ファーストクラスのクラスなど、他の「ファーストクラス」について話すこともできる)か、そうでないかを思い出すことだと思います。したがって、特定の関数がファーストクラスであるかどうかについて決して話しません。OTOHは、関数が高次かどうかというと、それが関数に対して動作するかどうかということなので、「高次性」は個々の関数の性質です。したがって、「ファーストクラスの関数を持っている」は言語のプロパティであり、「高次である」は関数のプロパティです。
ベン

まさにベン。これら2つはどちらも機能のプロパティであると考えていたため、混乱しました。コメントありがとうございます。
Simon

また、「ファーストクラスの関数」はクロージャのサポートと同じではないことに注意してください。たとえば、Cでは、関数ポインターを介して「ファーストクラス関数」をサポートしています。ただし、Cはネストされた関数の概念をサポートしていないため、クロージャーをサポートしていません。
Tac-Tics 2012

1
@ Tac-Tics定義は確かに主観的で議論の余地がありますが、個人的には、Cは(関数ポインターを介して)より高次の関数のみをサポートするものだと考えるのが好きです。ただし、ファーストクラスの関数はサポートされていません。関数は、intやのような他の値の型よりも劣っています。つまりchar、どこでも(関数の本体によって)明示的に定義できないからです。
wlnirvana 2017

67

ファーストクラスの関数は、オブジェクトのように扱われる(または変数に割り当てることができる)関数です。

高次関数は、少なくとも1つのファーストクラス関数をパラメーターとして取るか、少なくとも1つのファーストクラス関数を返す関数です。


20

彼らは違います。

ファーストクラスの機能

言語全体の値が一律に処理される値は、「ファーストクラス」と呼ばれます。それらは、データ構造に格納されるか、引数として渡されるか、制御構造で使用されます。

関数型の値をサポートし、それらを非関数値と同じように扱う言語は、「ファーストクラス関数」を持つと言えます。

高次関数

ファーストクラスの関数があることの結果の1つは、関数を引数として別の関数に渡すことができるはずです。後者の関数は「高次」になりました。関数を引数として取る関数です。

正規の例は「マップ」です

map :: (a -> b) -> [a] -> [b]
map f []     = []
map f (x:xs) = f x : map f xs

つまり、関数と配列を受け取り、各要素に関数が適用された新しい配列を返します。

関数型言語(関数がプログラムを構築する主要な手段である言語)はすべて、ファーストクラスの関数を備えています。ほとんどはより高次の関数も持っています(Excelのような言語は非常にまれな例外であり、機能的であると言えますが、より高次ではありません)。


1
ドンありがとう。それは包括的です。そして、フェーズ「結果の1つ」は、これら2つの間の一種の関係を示していると思います。
Simon

10

前の回答に加えて、ファーストクラスの関数を使用する言語では、高次関数の式が自動的に有効になることに注意してください(関数を他の値と同様にパラメーターとして渡すことができるため)。

一方、高階関数をサポートするが、関数をファーストクラスにしない(そして関数であるパラメーターが特別に扱われ、「通常の」値パラメーターとは異なる)言語を想像できます。

したがって、(言語機能としての)ファーストクラス関数の存在は、高次関数の存在を意味しますが、その逆は意味しません。


高次関数がファーストクラス関数ではない例を挙げていただけますか。(私は両方とも同じだと思いました。)
ATHER

@ATHER、私はそのような機能のためにそのようなデザインの選択をする言語の具体的な例を持っていません。しかし、たとえばC ++のテンプレートの場合も同様です。テンプレートは高次( "テンプレートテンプレートパラメータ"を持つことができます)ですが、ファーストクラスの値ではありません。つまり、テンプレートを通常の関数のパラメータにすることはできません。同様に、たとえばMLのモジュール/ファンクターを使用します。
Andreas Rossberg

@AndreasRossberg Java 8は彼の質問に対する有効な答えではないでしょうか?関数はファーストクラスのシチズンではありませんが、Java関数は(関数型インターフェースを介して)関数を受け取ることができます。
Abdul

1

ファーストクラス関数は次のことができます。

  • 変数に格納される
  • 関数から返される。
  • 引数として別の関数に渡されます。

高次関数は、別の関数を返す関数です。

例えば:

function highOrderFunc() {
  return function () {
    alert('hello');
  };
}

0

ファーストクラスの関数とは、他の型(変数、ブール値、数値...)で実行できるすべてのことを意味し、関数で実行できます。

たとえば、それらを変数に割り当て、渡し、オンザフライで作成します。

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