Qual é o nome de uma função que não aceita argumentos e não retorna nada? [fechadas]


80

No java.util.functionpacote do Java 8 , temos:

  • Função : Pega um argumento, produz um resultado.
  • Consumidor : Aceita um argumento, não produz nada.
  • Fornecedor : Não aceita argumentos, produz um resultado.
  • ... : Outros casos de manipulação de primitivas, 2 argumentos, etc ...

Mas preciso lidar com o caso " não aceita argumentos, não produz nada ".

Não há nada para isso java.util.functionnal.

Então, a questão é:

Qual é o nome de ' uma função que não aceita argumentos e não retorna nada '?

No Java 8, sua definição seria:

@FunctionalInterface
public interface InsertANameHere {
    void execute();
}

O executor já existe e tem outro objetivo: " Um objeto que executa tarefas Runnable enviadas ". A assinatura não corresponde a ( execute(Runnable):void) e nem sequer é uma interface funcional .

O executável existe, mas está fortemente vinculado ao contexto de segmentação:

  • O pacote java.langnão é java.util.function.
  • O javadoc declara: " A interface Runnable deve ser implementada por qualquer classe cujas instâncias sejam executadas por um encadeamento ".
  • O nome "Runnable" sugere algum código em execução dentro de um thread.

28
"Mas não há nada para" Não aceita argumentos, não produz nada "" - Runnable ?
user11153

11
Eu acho que o javadoc para Runnableestá desatualizado neste momento, porque um Runnable também é usado por outras classes além de Thread( Executorpor exemplo).
SpaceTrucker

13
@ superbob Isso não significa que Runnables só pode ser .run()por Threads. Na verdade eles estão muito comumente usado para exatamente o propósito descrito na pergunta
blgt

5
@superbob Esse era seu objetivo inicial, mas desde o Java 8 foi "adaptado" como interface funcional. É por isso que você não encontrou nada no java.util.function pacote.
user11153

5
Semi-Snark: ImpureFuntion porque certamente depende apenas de efeitos colaterais, caso contrário, é um não-op. ( pt.wikipedia.org/wiki/Pure_function#Impure_functions ) Mais seriosuly: imperativo (faça alguma coisa), que corresponderia pelo menos à semântica de void execute ();
Kristian H

Respostas:


71

A escolha de Java de fazê-lo dessa maneira com um nome separado para cada aridade foi estúpida. Não vale exatamente a pena emular. No entanto, se você precisar por uma questão de consistência ou se estiver escrevendo um código de biblioteca muito genérico, as sugestões do Konrad são boas. Eu posso jogar Procedureno ringue.

Usar um paradigma pseudo-funcional não significa que os princípios normais de nomeação devam sair pela janela. As interfaces devem quase sempre receber o nome do que fazem , não de alguma idéia sintática genérica. Se as funções forem colocadas em uma pilha de desfazer, elas deverão ser nomeadas UndoFunction. Se eles são chamados a partir de eventos da GUI, devem ser nomeados GUIEventHandler. Amigos não permitem que amigos perpetuem convenções de nomenclatura incorreta.


Procedureestá bem também. Para o contexto, estou desenvolvendo uma biblioteca genérica que precisa lidar com esse tipo de "estrutura".
Superbob

18
Eu gosto Proceduredos meus dias pascal. A Proceduretem efeitos colaterais, a Functionnão. Como você não retorna um valor, a única coisa que ele pode fazer é ter um efeito colateral.
Spencer Rathbun

Eu posso estar inclinado a usar ProcedureRIR<T1,T2>para void proc(T1, int, T2)e também para outros tipos - provavelmente criando a maioria deles sob demanda, em vez de tentar empinar em todas as combinações possíveis de tipos.
Supercat

1
De fato, a programação funcional real geralmente não incentiva a nomeação no estilo húngaro. Isso é mais a mentalidade do paradigma oo do que funcional.
precisa saber é

3
If the functions are placed into an undo stack, they should be named UndoFunction.Há uma diferença entre nomear a função e atribuir um tipo diferente. Em estilo funcional você não criaria um UndoFunctontipo porque agora você não pode passá-lo para flip, curry, compose, filter, map, etc. Na minha opinião , que é a verdadeira razão a decisão do Java para dar funções com diferentes arities nomes diferentes é estúpido. Claro, se você estiver usando efeitos colaterais, chame o que for; você já jogou composição pela janela e também não está usando funções.
Doval

33

No mundo java, é chamado Runnable. No mundo C #, é chamado Action.

Mas, existe um nome melhor que se encaixa perfeitamente em uma visão maior das coisas.

A visão mais ampla das coisas ocorre mais tarde, quando você decide que, além da sua interface funcional sem parâmetros, também precisa ter interfaces funcionais semelhantes que aceitem um, dois ou mais argumentos ou que retornam um valor. Quando isso acontecer, você desejará que os nomes de todas essas entidades sejam isomórficos e correspondam entre si.

Portanto, em Java, eu tenho meu próprio conjunto de interfaces funcionais que chamo de Procedures, definidas da seguinte maneira:

public interface Procedure
{
    void invoke();
}

public interface Procedure1<T1>
{
    void invoke( T1 argument1 );
}

... (você entendeu a foto.)

E também tenho um conjunto semelhante de interfaces chamado Functions, definido de maneira semelhante, com o primeiro parâmetro genérico sendo o tipo de retorno:

public interface Function<R>
{
    R invoke();
}

public interface Function1<R,T1>
{
    R invoke( T1 argument1 );
}

Então, o que quero dizer aqui é que esse Procedureé um nome muito bom porque se encaixa perfeitamente em uma visão mais ampla das coisas. Se você decidir posteriormente ter interfaces funcionais semelhantes com métodos que aceitam argumentos ou retornam um valor, você o encontrará.

NOTA: Eu basicamente concordo com a afirmação de Karl Bielefeldt de que "os princípios normais de nomeação não devem sair pela janela" e que "as interfaces quase sempre devem receber o nome do que fazem, não de alguma idéia sintática genérica". Mas note que mesmo ele permite "quase sempre". Às vezes, são necessários procedimentos e funções (essencialmente anônimos), e é isso que o OP está perguntando e é isso que estou respondendo.

Alteração 2017-11-10:

Você pode perguntar, por que em Function1<R,T1>vez de Function1<T1,R>? Poderia ser de qualquer maneira, mas tenho preferência pelos valores de retorno à esquerda, porque gosto de seguir a convenção de nomenclatura 'converter de' (destino de origem) em oposição à 'converter para' (origem para -destinação). (O que é mais um acidente do que uma convenção, na verdade, no sentido de que provavelmente ninguém nunca pensou nisso, porque, se tivessem pensado nisso, teriam chegado à convenção de 'conversão de'. )

Li sobre isso em Joel Spolksy - Fazendo o código errado parecer errado , é um artigo muito longo, que eu recomendo a leitura na íntegra, mas se você quiser pular direto para o caso em questão, procure por 'TypeFromType', mas para forneça TL; DR, a idéia é que myint = intFromStr( mystr )é muito melhor do que myint = strToInt( mystr ), porque no primeiro caso os nomes dos tipos estão próximos dos valores associados, para que você possa ver facilmente que o 'int' corresponde ao 'int' e o 'str' corresponde ao 'str'.

Então, por extensão, tenho a tendência de ordenar as coisas da maneira que elas aparecerão no código.


1
Esta solução é realmente boa, parece ainda mais à prova de balas do que o próprio Fornecedor, Consumidor, BiFunction, ..., porque define tudo apenas com dois conceitos. Isso me lembra a resposta de @Karl Bielefeldt sobre " a escolha de Java para fazê-lo dessa maneira com um nome separado para cada aridade [que] foi estúpida ". A única "desvantagem" é que ele não lida com tipos primitivos e suas combinações (coisas divertidas como DoubleToLongFunction, ToLongBiFunction, ...). Mas primitivos é outra preocupação ...
Superbob

Sim. Basicamente, uma vez que você começa a substituir genéricos por primitivos, isso significa que você realmente se importa com o desempenho; portanto, tudo bem se você se afastar da convenção apresentada aqui e usar nomes altamente personalizados para melhorar o desempenho.
Mike Nakis

1
Se eu pudesse aceitar uma segunda resposta, escolheria a sua graças às sugestões do Procedimento N , Função N. Eu ainda votei nele.
21315 superbob

Por que não é Function1<T1, R>?
ErikE

@ ErikE, é uma pergunta muito boa, e eu alterei meu post para respondê-lo.
Mike Nakis

18

Por que não Command? Dado que ele não recebe dados e não retorna dados, mas assumindo que chamá-los causa algum efeito (caso contrário, seria realmente inútil), imagino que seja praticamente a única coisa que pode fazer - acionar uma ação, fazer alguma coisa acontecer.

Falando nisso, também há um Actiondelegado genérico no .NET. Ao contrário do Java Consumer, pode levar de 0 a 16 argumentos; em outras palavras, a versão mais simples não é necessária - consulte o MSDN .

E como o nome não implica que haja algo para "consumir", também parece ser uma boa escolha de nome.


1
Commandé bom. Pode ser confundido com o padrão de comando, mas pode ser a solução.
22315 superbob

7
Eu gosto Actionmais do que Command. Um comando soa mais como algo que é recebido e avaliado, enquanto uma ação é executada por seus efeitos colaterais.
Bergi

7
Umm ... como pode não ser um padrão de comando? Você criou exatamente a entidade Command! Ele ainda tem o execute()método tradicionalmente nomeado . 0_o '
hijarian 20/03/2015

1
Não gosto da sugestão de ação, pois essa é uma interface Swing comum (e boa). Comando é razoável.
user949300

@ user949300, mas depende do contexto - Java é um mundo grande, sou desenvolvedor Android (agora) e não tenho idiossincrasias relacionadas ao J2EE;) Concordo, é claro, que a convenção de nomenclatura escolhida não deve colidir com aquele que sua estrutura usa.
precisa
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.