Im Java 8- java.util.function
Paket haben wir:
- Funktion : Nimmt ein Argument und erzeugt ein Ergebnis.
- Verbraucher : Nimmt ein Argument, produziert nichts.
- Lieferant : Nimmt kein Argument, produziert ein Ergebnis.
- ... : Andere Fälle, die Primitive, 2 Argumente usw. behandeln ...
Aber ich muss den Fall " nimmt kein Argument, produziert nichts " behandeln.
Es gibt nichts dafür in java.util.functionnal
.
Die Frage ist also:
Wie heißt eine Funktion, die kein Argument annimmt und nichts zurückgibt ?
In Java 8 wäre seine Definition:
@FunctionalInterface
public interface InsertANameHere {
void execute();
}
Executor ist bereits vorhanden und hat einen anderen Zweck: " Ein Objekt, das übermittelte ausführbare Tasks ausführt ". Die Signatur stimmt nicht überein ( execute(Runnable):void
) und ist nicht einmal eine funktionierende Schnittstelle .
Runnable existiert, ist aber stark mit dem Threading-Kontext verbunden:
- Das Paket ist
java.lang
nichtjava.util.function
. - Im Javadoc heißt es: " Die Runnable-Schnittstelle sollte von jeder Klasse implementiert werden, deren Instanzen von einem Thread ausgeführt werden sollen ."
- Der Name "Runnable" deutet auf einen laufenden Code innerhalb eines Threads hin.
java
functional-programming
java8
Superbob
quelle
quelle
Runnable
zu diesem Zeitpunkt veraltet ist, da ein Runnable auch von anderen Klassen alsThread
(Executor
zum Beispiel) verwendet wird.Runnable
s nur.run()
vonThread
s sein kann. Tatsächlich werden sie sehr häufig für genau den in der Frage beschriebenen Zweck verwendetjava.util.function
Paket gefunden.Antworten:
Javas Entscheidung, es so zu machen, mit einem eigenen Namen für jede Arität, war dumm. Es lohnt sich nicht, es zu emulieren. Wenn Sie dies jedoch aus Gründen der Konsistenz tun müssen oder wenn Sie sehr allgemeinen Bibliothekscode schreiben, sind Konrads Vorschläge gut. Ich könnte
Procedure
in den Ring werfen .Die Verwendung eines pseudofunktionalen Paradigmas bedeutet nicht, dass normale Benennungsprinzipien aus dem Fenster verschwinden sollten. Interfaces sollten fast immer nach dem benannt werden, was sie tun , nicht nach einer generischen syntaktischen Idee. Wenn die Funktionen in einem Rückgängig-Stapel abgelegt werden, sollten sie benannt werden
UndoFunction
. Wenn sie von GUI-Ereignissen aufgerufen werden, sollten sie benannt werdenGUIEventHandler
. Freunde lassen Freunde keine schlechten Namenskonventionen aufrechterhalten.quelle
Procedure
ist auch in Ordnung. Für den Kontext entwickle ich eine generische Bibliothek, die mit dieser Art von "Struktur" umgehen muss.Procedure
von meinen Pascal-Tagen. AProcedure
hat Nebenwirkungen, aFunction
nicht. Da Sie keinen Wert zurückgeben, kann dies nur zu Nebenwirkungen führen.ProcedureRIR<T1,T2>
fürvoid proc(T1, int, T2)
und auch für andere Typen zu verwenden - wahrscheinlich werden die meisten von ihnen auf Anfrage erstellt, anstatt zu versuchen, jede mögliche Kombination von Typen zu stopfen.If the functions are placed into an undo stack, they should be named UndoFunction.
Es gibt jedoch einen Unterschied zwischen der Benennung der Funktion und der Zuweisung eines anderen Typs. In funktionalem Stil würden Sie keine erstellenUndoFuncton
Art , denn jetzt können Sie es nicht passieren zuflip
,curry
,compose
,filter
,map
, usw. Meiner Meinung nach, dass der wahre Grund ist Java Entscheidungsfunktionen zu geben , mit verschiedenen arities verschiedene Namen dumm. Natürlich, wenn Sie Nebenwirkungen verwenden wollen, nennen Sie es wie auch immer; Sie haben die Komposition bereits aus dem Fenster geworfen und verwenden vermutlich auch keine Funktionen.In der Java-Welt heißt es
Runnable
. In der C # -Welt heißt esAction
.Es gibt jedoch einen besseren Namen, der sich gut in eine größere Sicht der Dinge einfügt.
Die größere Sicht der Dinge wird später deutlich, wenn Sie entscheiden, dass Sie neben Ihrer parameterlosen Void-Funktionsschnittstelle auch ähnliche Funktionsschnittstellen benötigen, die ein, zwei oder mehr Argumente akzeptieren oder einen Wert zurückgeben. In diesem Fall möchten Sie, dass die Namen aller dieser Entitäten isomorph sind und miteinander korrespondieren.
In Java habe ich also meine eigenen Funktionsschnittstellen, die ich
Procedure
s nenne und die wie folgt definiert sind:... (du bekommst das Bild.)
Und ich habe auch einen ähnlichen Satz von Schnittstellen namens
Function
s, die auf ähnliche Weise definiert sind, wobei der erste generische Parameter der Rückgabetyp ist:Mein Punkt hier ist also, dass dies
Procedure
ein sehr guter Name ist, weil er sich gut in eine größere Sicht der Dinge einfügt. Wenn Sie sich später für ähnliche funktionale Schnittstellen mit Methoden entscheiden, die Argumente akzeptieren oder einen Wert zurückgeben, werden Sie darauf stoßen.ANMERKUNG: Ich stimme im Grundemit Karl Bielefeldts Behauptung überein , dass "normale Benennungsprinzipien [nicht] aus dem Fenster gehen sollten" und dass "Schnittstellen fast immer nach dem benannt werden sollten, was sie tun, nicht nach einer generischen syntaktischen Idee". Aber beachte, dass selbst er "fast immer" zulässt. Manchmal werden (im Wesentlichen anonyme) Verfahren und Funktionen benötigt, und das fragt das OP, und darauf antworte ich.
Änderung 2017-11-10:
Sie könnten fragen, warum
Function1<R,T1>
stattFunction1<T1,R>
? Es könnte in beide Richtungen gehen, aber ich bevorzuge Rückgabewerte auf der linken Seite, da ich die Namenskonvention "Konvertieren von" (Ziel von Quelle) im Gegensatz zur Namenskonvention "Konvertieren nach" (Quelle zu) befolgen möchte Konvention. (Was eher ein Unfall als eine Konvention ist, in dem Sinne, dass höchstwahrscheinlich niemand darüber nachgedacht hat, denn wenn sie überhaupt darüber nachgedacht hätten, wären sie zu der Konvention gekommen, von der aus man konvertiert. )Ich habe darüber in Joel Spolksy - Falschen Code falsch aussehen lassen gelesen. Es ist ein sehr langer Artikel, den ich in seiner Gesamtheit empfehle. Wenn Sie jedoch direkt zum vorliegenden Fall springen möchten, suchen Sie nach 'TypeFromType', aber nach ' Geben Sie die TL; DR ein, die Idee ist, dass dies
myint = intFromStr( mystr )
viel besser ist alsmyint = strToInt( mystr )
, da im ersten Fall die Namen der Typen nahe an den zugeordneten Werten liegen, sodass Sie leicht erkennen können, dass das 'int' mit dem 'int' und übereinstimmt das 'str' stimmt mit dem 'str' überein.Daher neige ich dazu, die Dinge so zu ordnen, wie sie im Code erscheinen werden.
quelle
Function1<T1, R>
?Warum nicht
Command
? Angesichts der Tatsache, dass es keine Daten akzeptiert und keine Daten zurückgibt, aber unter der Annahme, dass das Aufrufen einen gewissen Effekt hat (andernfalls wäre es wirklich ziemlich sinnlos), stelle ich mir vor, dass dies in etwa das einzige ist, was es tun kann - eine Aktion auslösen, etwas bewirken.Apropos, es gibt auch einen allgemeinen
Action
Delegaten in .NET. Im Gegensatz zu JavaConsumer
kann es 0 bis 16 Argumente annehmen. Mit anderen Worten, die einfachste Version benötigt keine - siehe MSDN .Und da der Name nicht bedeutet, dass es etwas zu "konsumieren" gibt, scheint es auch eine gute Namenswahl zu sein.
quelle
Command
ist gut. Es kann mit dem Befehlsmuster verwechselt werden , aber es könnte die Lösung sein.Action
mehr alsCommand
. Ein Befehl klingt eher nach etwas, das empfangen und ausgewertet wird, während eine Aktion auf ihre Nebenwirkungen hin ausgeführt wird.execute()
Methode. 0_o '