Os métodos encadeados que requerem apenas um parâmetro por método equivalem ao currying?

15

Ultimamente, tenho brincado com Ruby e me perguntei se, em linguagens orientadas a objetos puras (e mesmo naquelas que não são puras), criar métodos que usam apenas um parâmetro e depois se acorrentam é equivalente a currying em linguagens com um funcional estilo? Se não, por que não? Eu apreciaria uma resposta detalhada e até rigorosa sobre o assunto.

Engenheiro Mundial
fonte

Respostas:

14

O encadeamento de métodos em linguagens orientadas a objetos é um pouco diferente de currying. Por definição , o resultado do curry é uma forma mais restrita da função original . Por convenção , o resultado do encadeamento de métodos é uma forma modificada do objeto original (geralmente sem função) . O encadeamento de métodos pode ser usado com métodos não relacionados na mesma classe, enquanto o curry envolve o retorno de uma função em que um ou mais parâmetros da função original são fixos (predeterminados).

Em Java, o encadeamento de métodos é como:

String myString = new StringBuilder("Hi ").append(firstName)
                                          .append(" ")
                                          .append(lastName)
                                          .append("!")
                                          .toString();

Portanto, cada uma dessas chamadas de método .append () retorna um ponteiro para o objeto StringBuilder anônimo. Este objeto está completo após cada .append () e não é uma função.

Por outro lado, em Scala, aplicação parcial ou curry é como:

def simple(x:Int, y:Int, z:Int) = x * (y + z)
val simpler = simple(2, _:Int, _:Int)
simpler(3, 4) => 14

(Amostra retirada do blog de Daniel Yankowsky )

simpler()neste exemplo é uma função de invólucro para simple(). simpler()ainda é uma função que usa mais parâmetros antes de poder avaliar algo além de uma versão mais limitada de si mesma.

EDIT: Lendo isso um dia depois, acho que "wrapper-function" é a chave. A aplicação de currying ou parcial pode ser melhor simulada em Java com métodos de wrapper.

public interface Simpler {
    public int apply(int y, int z);
}

public class Simple {
    public int apply(int x, int y, int z) { return x * (y + z); }

    public Simpler partiallyApply(final int x) {
        final simple = this;
        return new Simpler() {
            @Override
            public int apply(int y, int z) {
                // x is the final int parameter to partiallyApply()
                simple.apply(x, y, z);
            }
        }
    }
}

: END-EDIT

O encadeamento de métodos pode ser semelhante a aplicação parcial ou currying, mas só pode ser equivalente a métodos que retornam outros métodos (consulte Functors) e, em seguida, os métodos precisam ser configurados com tipos de retorno que modelem significativamente o currying ou aplicação parcial.

O encadeamento de métodos é mais frequentemente usado para implementar algo como avaliação lenta, como é feito com o padrão de design "Builder" e as novas interfaces da Library Library no Java 8 .

Espero que ajude.

GlenPeterson
fonte
+1: eu sabia disso, mas acho que não poderia ter articulado isso tão perto quanto você.
Peter13
Bem explicado, aqui está uma marca de seleção verde e uma votação positiva para o seu problema.
World Engineer
Pergunta sobre o belo exemplo de StringBuilder - sem a toString()chamada, não estamos replicando efetivamente a intenção de currying em nossa chamada? Eu só estou tentando entender o conceito de curry no OO.
Sridhar Sarnobat 20/03/2015
1
@ Sridhar-Sarnobat uma função ao curry retorna outra função com menos parâmetros. Os parâmetros eliminados são transformados em constantes internas na função retornada. Alguns objetos são tratados como funções no Java 8, o que pode tornar isso confuso, mas o StringBuilder não é um deles. Hmm, no StringBuilder, a append(charSeq)função é uma forma ao curry da insert(destOffset, charSeq)função, destOffsetsempre com o comprimento do StringBuilder.
GlenPeterson