En el java.util.function
paquete de Java 8 , tenemos:
- Función : toma un argumento, produce un resultado.
- Consumidor : toma un argumento, no produce nada.
- Proveedor : no toma argumentos, produce un resultado.
- ... : Otros casos que manejan primitivas, 2 argumentos, etc.
Pero necesito manejar el caso " no toma argumento, no produce nada ".
No hay nada para esto en java.util.functionnal
.
Entonces, la pregunta es:
¿Cuál es el nombre de ' una función que no toma argumentos y no devuelve nada '?
En Java 8, su definición sería:
@FunctionalInterface
public interface InsertANameHere {
void execute();
}
El ejecutor ya existe y tiene otro propósito: " Un objeto que ejecuta tareas ejecutables enviadas ". La firma no coincide ( execute(Runnable):void
) y ni siquiera es una interfaz funcional .
Runnable existe, pero está fuertemente vinculado al contexto de subprocesos:
- El paquete
java.lang
no lo esjava.util.function
. - El javadoc dice: " La interfaz Runnable debe ser implementada por cualquier clase cuyas instancias estén destinadas a ser ejecutadas por un hilo ".
- El nombre "Runnable" sugiere un código en ejecución dentro de un hilo.
java
functional-programming
java8
superbob
fuente
fuente
Runnable
está desactualizado en este momento, porque un Runnable también es utilizado por otras clases queThread
(Executor
por ejemplo).Runnable
s solo pueda ser.run()
porThread
s. De hecho, se usan muy comúnmente para exactamente el propósito descrito en la preguntajava.util.function
paquete.Respuestas:
La elección de Java de hacerlo de esa manera con un nombre separado para cada arity fue estúpida. No vale exactamente la pena emular. Sin embargo, si debe hacerlo en aras de la coherencia, o si está escribiendo un código de biblioteca muy genérico, las sugerencias de Konrad son buenas. Podría arrojarme
Procedure
al ring.El uso de un paradigma pseudo-funcional no significa que los principios normales de nomenclatura deberían desaparecer. Las interfaces casi siempre deben nombrarse por lo que hacen , no por alguna idea sintáctica genérica. Si las funciones se colocan en una pila de deshacer, deben nombrarse
UndoFunction
. Si se invocan desde eventos de la GUI, deben nombrarseGUIEventHandler
. Los amigos no dejan que los amigos perpetúen las convenciones de nombres erróneos.fuente
Procedure
está bien también Para el contexto, estoy desarrollando una biblioteca genérica que necesita manejar este tipo de "estructura".Procedure
de mis días pascales. AProcedure
tiene efectos secundarios, aFunction
no. Como no devuelve un valor, lo único que podría hacer es tener un efecto secundario.ProcedureRIR<T1,T2>
paravoid proc(T1, int, T2)
, y del mismo modo para otros tipos, probablemente creando la mayoría de ellos a pedido en lugar de tratar de incluir todas las combinaciones posibles de tipos.If the functions are placed into an undo stack, they should be named UndoFunction.
Sin embargo, hay una diferencia entre nombrar la función y darle un tipo diferente. En estilo funcional que no genere unUndoFuncton
tipo porque ahora no se puede pasar aflip
,curry
,compose
,filter
,map
, etc, en mi opinión de que es la verdadera razón de la decisión de Java para dar funciones diferentes con diferentes nombres arities es estúpida. Por supuesto, si vas a usar efectos secundarios, llámalo como sea; ya arrojaste la composición por la ventana y posiblemente tampoco estés usando funciones.En el mundo de Java, se llama
Runnable
. En el mundo C #, se llamaAction
.Pero, hay un nombre mejor que se adapta muy bien a una vista más amplia de las cosas.
La vista más amplia de las cosas llega más tarde, cuando decides que, además de tu interfaz funcional sin parámetros, también necesitas tener interfaces funcionales similares que acepten uno, dos o más argumentos, o que devuelvan un valor. Cuando eso suceda, querrá que los nombres de todas esas entidades sean isomorfos y correspondan entre sí.
Entonces, en Java, tengo mi propio conjunto de interfaces funcionales que llamo
Procedure
s, definidas de la siguiente manera:... (te dan la imagen.)
Y también tengo un conjunto similar de interfaces llamado
Function
s, definido de manera similar, siendo el primer parámetro genérico el tipo de retorno:Entonces, mi punto aquí es que
Procedure
es un muy buen nombre porque encaja perfectamente en una visión más amplia de las cosas. Si luego decide tener interfaces funcionales similares con métodos que aceptan argumentos o devuelven un valor, se encontrará con esto.NOTA: Básicamente , estoy de acuerdo con la afirmación de Karl Bielefeldt de que "los principios de denominación normales [no] deben salir por la ventana" y que "las interfaces casi siempre deben nombrarse por lo que hacen, no por alguna idea sintáctica genérica". Pero tenga en cuenta que incluso él permite "casi siempre". A veces hay una necesidad de procedimientos y funciones (esencialmente anónimas), y eso es lo que pide el OP, y eso es lo que estoy respondiendo.
Enmienda 2017-11-10:
Usted podría preguntar, ¿por qué en
Function1<R,T1>
lugar deFunction1<T1,R>
? Podría ir en cualquier dirección, pero tengo preferencia por los valores de retorno a la izquierda porque me gusta seguir la convención de nomenclatura 'convertir-de' (destino-de-fuente) en lugar de 'convertir-a' (fuente-a -destinación). (Lo cual es más un accidente que una convención, en realidad, en el sentido de que lo más probable es que nadie lo haya pensado, porque si lo hubieran pensado, habrían llegado a la convención de 'conversión de'. )Leí sobre esto en Joel Spolksy: hacer que el código incorrecto parezca incorrecto , es un artículo muy largo, que recomiendo leer en su totalidad, pero si desea saltar directamente al caso en cuestión, busque 'TypeFromType', pero para darle la TL; DR, la idea es que
myint = intFromStr( mystr )
es mucho mejor quemyint = strToInt( mystr )
, porque en el primer caso los nombres de los tipos están cerca de los valores asociados, por lo que puede ver fácilmente que 'int' coincide con 'int' y el 'str' coincide con el 'str'.Entonces, por extensión, tiendo a ordenar las cosas en la forma en que aparecerán en el código.
fuente
Function1<T1, R>
?¿Por qué no
Command
? Dado que no toma datos y no devuelve datos, pero suponiendo que llamarlo causa algún efecto (de lo contrario, sería bastante inútil en realidad), imagino que eso es aproximadamente lo único que puede hacer: disparar una acción, hacer que algo suceda.Hablando de eso, también hay un
Action
delegado genérico en .NET. A diferencia de Java,Consumer
puede tomar de 0 a 16 argumentos; en otras palabras, la versión más simple de la misma no requiere nada; vea MSDN .Y dado que el nombre no implica que haya algo para "consumir", también parece una buena elección de nombre.
fuente
Command
es bueno. Se puede confundir con el patrón de Comando, pero podría ser la solución.Action
más queCommand
. Un comando suena más como algo que se recibe y evalúa, mientras que se ejecuta una acción por sus efectos secundarios.execute()
método tradicionalmente nombrado . 0_o '