Czy metody powiązane, które wymagają tylko jednego parametru na metodę, są równoważne curry?

15

Ostatnio bawiłem się z Ruby i zastanawiałem się, czy w czysto obiektowych językach (a nawet tych, które nie są czyste) tworzenie metod, które przyjmują tylko jeden parametr, a następnie łączą się, jest równoważne curry w językach z funkcjonalnym styl? Jeśli nie, dlaczego nie? Byłbym wdzięczny za szczegółową, a nawet rygorystyczną odpowiedź na ten temat.

Inżynier świata
źródło

Odpowiedzi:

14

Łańcuchy metod w językach obiektowych nieco różnią się od curry. Z definicji wynik curry jest bardziej ograniczoną formą oryginalnej funkcji . Zgodnie z konwencją wynikiem łączenia metod jest zmodyfikowana forma oryginalnego (zwykle niefunkcjonalnego) obiektu . Łańcuch metod można stosować z niepowiązanymi metodami w tej samej klasie, podczas gdy curry obejmuje zwrócenie funkcji, w której jeden lub więcej parametrów funkcji pierwotnej jest ustalonych (z góry określonych).

W Javie tworzenie łańcuchów metod przypomina:

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

Zatem każde z tych wywołań metody .append () zwraca wskaźnik do anonimowego obiektu StringBuilder. Ten obiekt jest uzupełniany po każdym .append () i nie jest funkcją.

Natomiast w Scali częściowe nakładanie lub curry przypomina:

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

(Próbka pochodzi z bloga Daniela Jankowskiego )

simpler()w tym przykładzie jest funkcja otoki dla simple(). simpler()jest nadal funkcją, która wymaga więcej parametrów, zanim będzie mogła ocenić wszystko, ale bardziej ograniczoną wersję samego siebie.

EDYCJA: Czytając to dzień później, myślę, że „funkcja opakowania” jest kluczem. Curry lub częściowa aplikacja najlepiej symulować w Javie metodami otoki.

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);
            }
        }
    }
}

: EDYCJA KOŃCOWA

Łańcuch metod może być podobny do częściowej aplikacji lub curry, ale może być równoważny tylko z metodami, które zwracają inne metody (wyszukiwanie Functors), a następnie metody muszą zostać skonfigurowane z typami zwracającymi, które w znaczący sposób modelują curry lub częściową aplikację.

Łańcuch metod jest częściej używany do implementacji czegoś w rodzaju leniwej oceny, podobnie jak w przypadku wzorca projektowego „Builder” i nowych interfejsów Biblioteki kolekcji w Javie 8 .

Mam nadzieję że to pomogło.

GlenPeterson
źródło
+1: Wiedziałem o tym, ale nie wydaje mi się, żebym mógł wyrazić to tak blisko, jak ty.
Peter Rowell,
Dobrze wyjaśnione, oto zielony znacznik wyboru i głos za twoje problemy.
Inżynier światowy
Pytanie o bardzo ładny przykład StringBuilder - bez toString()połączenia nie jesteśmy w stanie skutecznie odtworzyć zamiaru curry w naszym wezwaniu? Po prostu staram się, aby koncepcja curry w OO była prosta.
Sridhar Sarnobat
1
@ Sridhar-Sarnobat funkcja curry zwraca inną funkcję o mniejszej liczbie parametrów. Usunięte parametry są przekształcane w stałe wewnętrzne w zwracanej funkcji. Niektóre obiekty są traktowane jak funkcje w Javie 8, co może powodować zamieszanie, ale StringBuilder nie jest jednym z nich. Hmm, w StringBuilder append(charSeq)funkcja to curry forma insert(destOffset, charSeq)funkcji, w której destOffsetzawsze jest długość StringBuilder.
GlenPeterson