Dans le java.util.function
package Java 8 , nous avons:
- Fonction : Prend un argument, produit un résultat.
- Consommateur : prend un argument, ne produit rien.
- Fournisseur : ne prend pas d'argument, produit un résultat.
- ... : Autres cas traitant des primitives, 2 arguments, etc ...
Mais je dois gérer le cas " ne prend pas d'argument, ne produit rien ".
Il n'y a rien pour cela dans java.util.functionnal
.
Donc, la question est:
Quel est le nom de " une fonction qui ne prend aucun argument et ne retourne rien "?
En Java 8, sa définition serait:
@FunctionalInterface
public interface InsertANameHere {
void execute();
}
Executor existe déjà et a un autre objectif: " Un objet qui exécute les tâches exécutables soumises ". La signature ne correspond pas ( execute(Runnable):void
) et n'est même pas une interface fonctionnelle .
Runnable existe, mais il est fortement lié au contexte de threading:
- Le paquet est
java.lang
, nonjava.util.function
. - Le javadoc indique: " L'interface Runnable doit être implémentée par toute classe dont les instances sont destinées à être exécutées par un thread ".
- Le nom "Runnable" suggère un code courant dans un thread.
java
functional-programming
java8
superbob
la source
la source
Runnable
est obsolète à ce stade, car un Runnable est également utilisé par d'autres classes queThread
(Executor
par exemple).Runnable
s ne peut être que.run()
parThread
s. En fait, ils sont très couramment utilisés exactement dans le but décrit dans la questionjava.util.function
paquet.Réponses:
Le choix de Java de le faire de cette façon avec un nom distinct pour chaque arité était stupide. Ce n'est pas exactement la peine d'émuler. Toutefois, si vous devez le faire par souci de cohérence ou si vous écrivez un code de bibliothèque très générique, les suggestions de Konrad sont bonnes. Je pourrais jeter
Procedure
dans le ring.L'utilisation d'un paradigme pseudo-fonctionnel ne signifie pas que les principes de dénomination normaux doivent disparaître. Les interfaces doivent presque toujours être nommées d'après ce qu'elles font , et non d'après une idée syntaxique générique. Si les fonctions sont placées dans une pile d'annulation, elles doivent être nommées
UndoFunction
. S'ils sont appelés à partir d'événements graphiques, ils doivent être nommésGUIEventHandler
. Les amis ne laissent pas leurs amis perpétuer les conventions de dénomination.la source
Procedure
est bien aussi. Pour le contexte, je développe une bibliothèque générique qui doit gérer ce type de "structure".Procedure
depuis mes jours pascal. UnProcedure
a des effets secondaires, unFunction
pas. Puisque vous ne renvoyez pas de valeur, la seule chose à faire est d’avoir un effet secondaire.ProcedureRIR<T1,T2>
pourvoid proc(T1, int, T2)
, et de la même manière, d’autres types - probablement en créant la plupart d’entre eux à la demande plutôt que d’essayer de créer toutes les combinaisons possibles de types.If the functions are placed into an undo stack, they should be named UndoFunction.
Cependant, il existe une différence entre nommer la fonction et lui attribuer un type différent. Dans un style fonctionnel , vous ne créeraient pas unUndoFuncton
genre parce que maintenant vous ne pouvez pas passer àflip
,curry
,compose
,filter
,map
, etc. À mon avis qui est la vraie raison de la décision de Java pour donner des fonctions différentes avec des noms différents arités est stupide. Bien sûr, si vous utilisez des effets secondaires, appelez-les comme vous le souhaitez. vous avez déjà jeté la composition par la fenêtre et vous n'utilisez probablement pas non plus de fonctions.Dans le monde java, cela s'appelle
Runnable
. Dans le monde C #, cela s'appelleAction
.Mais, il existe un meilleur nom qui s’intègre parfaitement dans une vision plus large des choses.
La vue d'ensemble des choses vient plus tard, lorsque vous décidez qu'en plus de votre interface fonctionnelle void sans paramètre, vous devez également disposer d'interfaces fonctionnelles similaires acceptant un, deux ou plusieurs arguments, ou renvoyant une valeur. Lorsque cela se produira, vous voudrez que les noms de toutes ces entités soient isomorphes et correspondants les uns aux autres.
Donc, en Java, j’ai mon propre ensemble d’interfaces fonctionnelles que j’appelle
Procedure
s, défini comme suit:... (vous avez l'image.)
Et j’ai aussi un ensemble similaire d’interfaces appelé
Function
s, défini de la même façon, le premier paramètre générique étant le type de retour:Donc, ce que je veux dire, c'est que
Procedure
c'est un très bon nom, car cela correspond parfaitement à une vision plus large des choses. Si vous décidez ultérieurement de disposer d'interfaces fonctionnelles similaires avec des méthodes acceptant les arguments ou renvoyant une valeur, vous devrez le rencontrer.NOTE: Je essentiellement suis d' accord avec l'affirmation de Karl Bielefeldt que «principes de nommage normaux doivent [pas] sortir par la fenêtre » et que « Interfaces doivent presque toujours être nomméesaprès ce qu'ils font, pas après une idée syntaxique générique. » Mais notez que même il permet "presque toujours". Parfois, des procédures et des fonctions (essentiellement anonymes) sont nécessaires, et c'est ce que demande le PO, et c'est ce à quoi je réponds.
Amendement 2017-11-10:
Vous pourriez demander, pourquoi
Function1<R,T1>
au lieu deFunction1<T1,R>
? Cela peut aller dans les deux sens, mais j'ai une préférence pour les valeurs de retour sur la gauche car j'aime bien suivre la convention de dénomination 'convertir à partir de (destination-de-source) par opposition à la conversion' à-convertir '(source à -destination) convention. (Ce qui est plus un accident qu'une convention, en réalité, en ce sens que probablement personne n’y a jamais pensé, parce que s’ils y avaient pensé du tout, ils seraient parvenus à la convention du "converti de". )J'ai lu à ce sujet dans Joel Spolksy - Making Wrong Code Look Wrong , il s'agit d'un très long article, que je recommande de lire dans son intégralité, mais si vous souhaitez passer directement à l'affaire, recherchez 'TypeFromType', mais vous donne le TL; DR, l’idée est que
myint = intFromStr( mystr )
c’est beaucoup mieux quemyint = strToInt( mystr )
, parce que dans le premier cas, les noms des types sont proches des valeurs associées, de sorte que vous pouvez facilement voir que le 'int' correspond au 'int' et le 'str' correspond au 'str'.Donc, par extension, j'ai tendance à ordonner les choses de la manière dont elles vont apparaître dans le code.
la source
Function1<T1, R>
?Pourquoi ne pas
Command
? Étant donné que cela ne prend aucune donnée et ne renvoie aucune donnée, mais en supposant que l'appel provoque un effet (sinon ce serait plutôt inutile), j'imagine que c'est à peu près la seule chose à faire: déclencher une action, faire bouger les choses.En parlant de cela, il existe également un
Action
délégué générique dans .NET. Contrairement à Java,Consumer
il peut prendre de 0 à 16 arguments. en d'autres termes, la version la plus simple ne prend rien - voir MSDN .Et puisque le nom n'implique pas qu'il y ait quoi que ce soit à "consommer", cela semble également être un bon choix de nom.
la source
Command
est bon. Cela peut être confondu avec le modèle de commande mais cela pourrait être la solution.Action
plus queCommand
. Une commande ressemble davantage à quelque chose qui est reçu et évalué, alors qu'une action est exécutée pour ses effets secondaires.execute()
méthode. 0_o '