一級市民機能とは何ですか?
Javaはファーストクラスシチズン機能をサポートしていますか?
編集:ウィキペディア
で言及されているように
関数型プログラミング スタイルには、ファースト クラス関数が必要です。
ファーストクラス関数の他の用途はありますか?
一級市民機能とは何ですか?
Javaはファーストクラスシチズン機能をサポートしていますか?
編集:ウィキペディア
で言及されているように
関数型プログラミング スタイルには、ファースト クラス関数が必要です。
ファーストクラス関数の他の用途はありますか?
プロシージャを「ファーストクラス」と見なす言語を使用すると、他の値と同じように関数を渡すことができます。
Java 7(およびそれ以前)やCの「種類」のような言語にはこの機能があります。Cでは関数ポインターを渡すことができますが、これらの言語で関数を動的に定義して、突然別の場所に渡すことはできません。バージョン8より前のJavaは、匿名クラスを使用してこれをある程度シミュレートできますが、技術的にはファーストクラスの関数を備えていません。
一方、C ++、D、C#、Visual Basic .NET、Java 8以降、および関数型言語(SchemeやHaskellなど)では、変数などの関数を渡すことができます。たとえば、次のコードは、入力に追加する関数を返します。addend
Dで書かれた:
int delegate(int) makeAdder(int addend) //Returns a function
{
return delegate int(int x) //Long way
{
return x + addend; //Notice that addend came from _outside_ the function
};
return (int x) { return x + addend; }; //Short way
return x => addend + x; //Super-short way, introduced in D 2.058
}
C#で書かれています:
Func<int, int> MakeAdder(int addend) //Returns a function
{
return delegate(int x) //The long way. Note: Return type is implicitly 'int'
{
return x + addend;
};
return x => x + addend; //Short way: x "goes to" (x + addend); inferred types
}
C ++で書かれています:
#include <functional>
std::function<int(int)> make_adder(int addend)
{
return [=](int x)
{
return addend + x;
};
}
Scalaで書かれた:
def makeAdder(addend: Int) = (x: Int) => addend + x
Pythonで書かれた:
def make_adder(addend):
def f(x):
return addend + x
return f
# or...
return lambda x: addend + x
Erlangで書かれた:
make_adder(Addend) ->
fun(X) -> Addend + X end.
JavaScriptで書かれています:
function makeAdder(addend) {
return function(x) {
return addend + x;
};
}
JavaScriptで記述(ES2015矢印関数構文):
const makeAdder = addend => x => addend + x;
スキームで書かれた:
(define (makeAdder addend)
(lambda (x)
(+ x addend)))
Haskellで書かれた:
makeAdder :: Int -> (Int -> Int)
makeAdder addend = \x -> addend + x
Visual Basic 2008での記述:
Function MakeAdder(addend As Integer) As Func(Of Integer, Integer)
Return Function(x) (x + addend)
End Function
Swiftで書かれています(冗長な実装と簡単な実装の両方):
func makeAdder(append: Int) -> (x: Int) -> Int {
return { (x: Int) -> Int in
return x + append
};
}
func makeAdder(append: Int) -> (Int) -> Int {
return {$0 + append};
}
(ちなみに、「ラムダ」は名前のない単なる関数です。ラムダは、ファーストクラスの関数をサポートする言語でのみサポートされています。)
関数が第一級市民である関数型プログラミングパラダイムの例を考えてみましょう。関数が第一級市民であると言うとき、関数を使用して次のことができます...
関数型プログラミング言語では、上記のことを行うことができます。
ここで、Java がファースト クラス シチズン関数をサポートしているかどうか (またはサポートしていないか) という質問に答えてみましょう。
Java では、メソッドは関数に相当します。上記のいずれもメソッドで行うことはできません。しかし、上記のすべては Java オブジェクトで可能です。したがって、オブジェクトは Java の第一級市民です。確かに、java8 は、関数型インターフェースとラムダ式を使用して、メソッド (正確にはメソッドの動作) を他のメソッドに渡すことをサポートしています。しかし、それはJavaが第一級市民としての機能を持っているという意味ではありません。
関数を渡したり、関数から関数を返すなど、上記のことを行う機能は非常に強力で便利です。これは、データだけでなく動作を渡すことができるためです。
ファースト クラス関数を渡すことができます。典型的な例は map 関数です。以下は、リストの要素を 2 乗する Scala の例です。
val square = (x:Int) => x*x
val squaredList = List(1,2,3,4).map(square _)
//--> List(1,4,9,16)
ここで、square 関数は map メソッドの引数であり、すべての要素に適用されます。Java でこのようなことをしたい場合は、次のようなクラスにラップされたメソッドを使用する必要があります。
interface F<A,B>{ B apply(A a); }
static <A,B> List<B> map(List<A> list, F<A,B> f) {
List<B> result = new ArrayList<B>();
for(A a:list) result.add(f.apply(a));
return result;
}
//we have to "wrap" the squaring operation in a class in order to make it a function
F<Integer,Integer> square = new F<Integer,Integer>(){
Integer apply(Integer a) { return a*a; }
}
List<Integer> ints = Arrays.<Integer>asList(1,2,3,4);
List<Integer> squares = map(ints, square);
これを見ると、Java で同じタスクを何らかの方法で実行できることがわかりますが、オーバーヘッドが増え、言語による「ネイティブ」サポートがなくても、回避策 (ラッパー クラス) を使用することによって実現できます。そのため、Java はファースト クラス関数をサポートしていませんが、それらを「シミュレート」できます。
願わくば、Java 8 がファースト クラス関数をサポートすることを願っています。これを今すぐサポートしたい場合は、http://functionaljava.org/またはhttp://functionalj.sourceforge.net/を参照するか、Scala 言語を参照してください。
ウィキペディアの定義は非常に優れています。これは、他のデータと同様に渡すことができる関数です。Java はそれらをサポートしていません。最も近いのはRunnable
andCallable
オブジェクトです。
関数は第一級市民であり、変数であるかのようにどこにでも関数を渡すことができることを意味します。
Scalaから
def isOdd(in: Int) = in % 2 == 1
val n = (1 to 10).toList
n.filter(isOdd)
see here: isOdd is a function. passed as if it's a variale.
Objects
Javaの第一級市民です。第一級市民はどこにでも通すことができる人です。パラレルは、国の第一級市民からのものであり、ほとんどどこでも許可されています。
読む:
いいえ、たとえば、変数にメソッドを割り当てたり、別のメソッドに引数として渡したりすることはできません。
代わりに、インターフェースを使用して意図した動作をラップしたり、リフレクションを使用してメソッドを具体化することができます。