什么是头等公民职能?

时间:2011-03-03 08:00:51

标签: java first-class-functions uses

什么是头等公民职能?

Java是否支持一流的公民功能?

编辑:
正如Wikepedia

所述
  

一流的功能是必需的   对于函数式编程风格。

是否还有其他第一类功能?

7 个答案:

答案 0 :(得分:47)

一种将程序视为"一流" 允许函数像任何其他值一样传递

Java 7(及更早版本)和C"等类型的#34;具有这种能力:C允许传递函数指针,但是你不能动态地定义那些语言中的函数,并突然传递到其他地方。版本8之前的Java可以在某种程度上使用匿名类模拟,但它在技术上并不具备一流的功能。

另一方面,C ++,D,C#,Visual Basic .NET,Java 8+和函数式语言(如Scheme和Haskell) do 允许您传递变量等函数。例如,下面的代码返回一个向其输入添加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;

写在Scheme:

(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};
}

(顺便说一下,&#34; lambda&#34;只是一个没有名字的函数。只有支持一流函数的语言才支持Lambda。)

答案 1 :(得分:3)

可以传递第一类函数。一个典型的例子是地图功能。下面是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语言。

答案 2 :(得分:1)

Wikipedia definition非常好 - 它是一个可以像任何其他数据一样传递的函数。 Java 支持它们。它最接近的是RunnableCallable个对象。

答案 3 :(得分:1)

让我们考虑功能编程范例的例子,其中函数是一等公民。当我们说功能是一等公民时,我们可以用功能......

做以下事情
  • 可以将功能分配给变量
  • 功能可以存储在数据结构中
  • 函数可以作为参数传递给其他函数
  • 可以从函数
  • 返回函数

在函数式编程语言中,可以执行上述操作。

现在,让我们尝试回答一个问题,即java是否支持头等公民职能(或)。

在java中,方法等同于函数。使用方法无法进行上述任何操作。但是使用java对象可以实现上述所有功能。因此,对象是java中的第一类公民。不可否认,java8支持使用函数接口和lambda表达式将方法(方法行为,准确)传递给其他方法。但这并不意味着java具有作为一等公民的功能。

执行上述功能,例如传递函数,从函数返回函数等功能非常强大且有用。这是因为,它允许我们传递行为而不仅仅是数据。

答案 4 :(得分:1)

上述@Alpine问题的答案主要是定义什么是头等函数以及示例。但是,仍然有一个问题为什么要使用?

我将尝试在Scala中回答一些不同的好处,在其中,一等函数将进一步用作高阶函数(map,flatMap),部分应用函数和Currying:

  1. 当我们专注于声明式编程时,处理数据的 how 部分留作 map,flatMap 的实现细节,而更多地关注于处理什么实际逻辑流程。 调用者可以指定要执行的操作,并保留高阶函数来处理实际的逻辑流。

  2. 部分应用的函数和Curinging:如果您想重用函数调用并保留一些参数以避免再次输入它们,该怎么办?

部分应用的功能示例:

def factorOf(x: Int, y: Int) = y % x == 0
val multipleOf3 = factorOf(3, _: Int)
val y = multipleOf3(78)

处理示例:

def factorOf(x: Int)(y: Int) = y % x == 0
val isEven = factorOf(2) _
val z = isEven(32)

上面的示例向您展示了如何通过不传递所有参数并保持代码 DRY 原理来重用一等函数的一部分。 这些使用一流功能的好处很少

有关更多详细信息,请参见:https://www.oreilly.com/library/view/learning-scala

答案 5 :(得分:0)

函数是一等公民意味着你可以将函数传递到任何地方,就像它是一个变量一样。

来自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中的一等公民。 一等公民是可以在任何地方通过的公民。并行来自一个国家的一等公民,几乎到处都是。

读:

答案 6 :(得分:0)

不,您不能将方法分配给变量或将其作为参数传递给另一个方法,例如。

相反,您可以使用接口来包装预期的行为,或使用反射来重新定义方法。