web-dev-qa-db-fra.com

Qu'est-ce qu'une fonction citoyenne de première classe?

Qu'est-ce qu'une fonction citoyenne de première classe?

Java prend-il en charge la fonction citoyenne de première classe?

Modifier:
Comme mentionné sur Wikepedia

Les fonctions de première classe sont une nécessité pour le style de programmation fonctionnelle.

Y a-t-il une autre utilisation des fonctions de première classe?

44
Alpine

Un langage qui considère les procédures comme "de première classe" permet de passer des fonctions comme n'importe quelle autre valeur .

Les langages comme Java 7 (et versions antérieures) et C "sorte de" ont cette capacité: C permet aux pointeurs de fonction d'être transmis, mais vous ne pouvez pas définir dynamiquement une fonction dans ces langages et soudainement passez cela ailleurs. Java avant la version 8 peut simuler ceci dans une certaine mesure avec des classes anonymes, mais il ne le fait pas pas techniquement avoir des fonctions de première classe.

D'autre part, C++, D, C #, Visual Basic .NET, Java 8+, et les langages fonctionnels (comme Scheme et Haskell) font vous permet de passer des fonctions comme des variables. Par exemple, le code ci-dessous renvoie une fonction qui ajoute addend à son entrée:

Écrit en 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
}

Écrit en 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
}

Écrit en C++:

#include <functional>

std::function<int(int)> make_adder(int addend)
{
    return [=](int x)
    {
        return addend + x;
    };
}

Écrit en Scala:

def makeAdder(addend: Int) = (x: Int) => addend + x

Écrit en Python:

def make_adder(addend):
    def f(x):
        return addend + x
    return f
    # or...
    return lambda x: addend + x

Écrit en Erlang:

make_adder(Addend) ->
    fun(X) -> Addend + X end.

Écrit en JavaScript:

function makeAdder(addend) {
    return function(x) {
        return addend + x;
    };
}

Écrit en JavaScript (syntaxe de la fonction de flèche ES2015):

const makeAdder = addend => x => addend + x;

Écrit dans le schéma:

(define (makeAdder addend)
  (lambda (x)
    (+ x addend)))

Écrit en Haskell:

makeAdder :: Int -> (Int -> Int)
makeAdder addend = \x -> addend + x

Écrit en Visual Basic 2008:

Function MakeAdder(addend As Integer) As Func(Of Integer, Integer)
    Return Function(x) (x + addend)
End Function

Écrit en Swift (implémentations verbeuses et abrégées):

func makeAdder(append: Int) -> (x: Int) -> Int {
    return { (x: Int) -> Int in
        return x + append
    };
}

func makeAdder(append: Int) -> (Int) -> Int {
    return {$0 + append};
}

(Soit dit en passant, un "lambda" est juste une fonction sans nom. Les lambdas ne sont pris en charge que dans les langages qui prennent en charge les fonctions de première classe.)

51
user541686

Une fonction de première classe peut être transmise. Un exemple typique est la fonction de carte. Voici un exemple dans Scala qui met en carré les éléments d'une liste:

val square = (x:Int) => x*x

val squaredList = List(1,2,3,4).map(square _)
//--> List(1,4,9,16)

La fonction carrée est ici un argument de la méthode map, qui l'applique à chaque élément. Si vous voulez faire quelque chose comme ça en Java, vous devez utiliser une méthode enveloppée dans une classe, quelque chose comme ceci:

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);

En regardant cela, vous pouvez voir que vous pouvez faire la même tâche d'une manière ou d'une autre en Java, mais avec plus de surcharge et sans prise en charge "native" par le langage, mais en utilisant une solution de contournement (classes wrapper). Donc Java ne prend pas en charge les fonctions de première classe, mais peut les "simuler".

Espérons que Java 8 supportera les fonctions de première classe. Si vous voulez avoir un certain support pour cela maintenant , regardez - http://functionaljava.org/ ou http://functionalj.sourceforge.net/ , ou jetez un œil à la langue Scala .

3
Landei

Prenons l'exemple du paradigme de programmation fonctionnelle dans lequel les fonctions sont les citoyens de première classe. Lorsque nous disons que les fonctions sont les citoyens de première classe, nous pouvons faire les choses suivantes avec la fonction ...

  • La fonction peut être affectée à une variable
  • La fonction peut être stockée dans une structure de données
  • La fonction peut être transmise comme argument aux autres fonctions
  • La fonction peut être renvoyée par les fonctions

Dans les langages de programmation fonctionnels, il est possible de faire les choses mentionnées ci-dessus.

Maintenant, essayons de répondre à la question de savoir si Java prend en charge les fonctions citoyennes de première classe (ou) non.

En Java, les méthodes sont équivalentes aux fonctions. Il n'est pas possible de faire tout ce qui précède avec des méthodes. Mais tout ce qui précède est possible avec Java objets. Donc, objets sont les citoyens de première classe en Java. Certes, Java8 prend en charge le passage de méthodes (comportement de méthode, à être précis) à d'autres méthodes utilisant des interfaces fonctionnelles et des expressions lambda, mais cela ne signifie pas que Java a des fonctions de citoyens de première classe.

La possibilité de faire au-dessus de choses comme passer des fonctions, retourner des fonctions à partir de fonctions est très puissante et utile. En effet, cela nous permet de contourner le comportement et pas seulement les données.

1
Nagakishore Sidde

Le définition Wikipedia est assez bon - c'est une fonction qui peut être transmise comme n'importe quelle autre donnée. Java ne les prend pas en charge . Le plus proche est Runnable et Callable objets.

1
Ted Hopp

Non, vous ne pouvez pas affecter une méthode à une variable ou la passer comme argument à une autre méthode par exemple.

Au lieu de cela, vous pouvez utiliser des interfaces pour encapsuler le comportement souhaité ou une réflexion pour réifier les méthodes.

0
eljenso

Les fonctions sont des citoyens de première classe, ce qui signifie que vous pouvez transmettre la fonction n'importe où comme s'il s'agissait d'une variable.

Depuis 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 sont des citoyens de première classe en Java. Un citoyen de première classe est celui qui peut être passé n'importe où. Le parallèle d'un citoyen de première classe d'un pays est autorisé presque partout.

Lis:

0
Nishant