Posiadanie funkcji f, która przyjmuje argumenty x 1 , x 2 ,…, x n
- tj. f: X 1 × X 2 ×… × X n → Y
- curry redefiniuje f jako funkcję przyjmującą pojedynczy argument a 1, który odwzorowuje na jeszcze jedną funkcję. Ta technika jest przydatna do częściowego zastosowania, na przykład z pow
funkcją curry, którą moglibyśmy napisać exp = pow(e)
.
Przykład
Zakładając, że mamy następującą funkcję f przyjmującą trzy argumenty ( f: X 1 × X 2 × X 3 → Y ):
def f(a,b,c):
return a + b * c
Curry tej funkcji pozostawia nam f_curry: X 1 → (X 2 → (X 3 → Y)) , jeśli teraz wywołalibyśmy tę funkcję dwa razy f_curry(1)(2)
, otrzymalibyśmy funkcję ( h
) równoważną z następującym:
def h(c):
return 1 + 2 * c
Funkcję curry f
można zapisać w następujący sposób (Python 3):
def f_curry(a):
def g_curry(b):
def h(c):
return a + b * c
return h
return g_curry
Wyzwanie
Twoim wyzwaniem będzie wywołanie funkcji w sposób opisany powyżej, oto zasady:
- Wejście będzie funkcją blackboksa, która przyjmuje co najmniej 2 argumenty
- Funkcja wejściowa zawsze będzie miała stałą liczbę argumentów (w przeciwieństwie do
printf
podobnych, uwaga: musisz obsługiwać funkcje z dowolną liczbą argumentów ≥2) - Jeśli twój język domyślnie korzysta z funkcji curry (np. Haskell), możesz oczekiwać, że funkcja wejściowa zostanie zdefiniowana w liczbie N -zamiast zamiast „funkcji wyższego rzędu”
- Jako argument można przyjąć liczbę argumentów
- Dane wyjściowe będą curry równoważnikiem *
- Możesz założyć, że funkcją wyjściową będzie zawsze:
- wywoływany z mniejszą lub równą liczbą argumentów pobieranych przez funkcję wejściową
- wywoływany z argumentami odpowiedniego typu
* Oznaczałoby to dla wejścia f
z N
argumentami i mocy h
, że dla wszystkich ważnych argumentów a1,…,aN
jest warunek f(a1,a2,…,aN) == h(a1)(a2)…(aN)
.
def f(a,b,c): return a + b * c
i wyjście jestdef f_curry(a): def g_curry(b): def h(c): return a + b * c return h return g_curry
?f
(które gdzieś zdefiniowane), a dane wyjściowe powinny być czymś równoważnymf_curry
. Albo wejście byłoby,lambda a,b,c: a+b*c
a wyjście funkcją równoważnąf_curry
.Odpowiedzi:
JavaScript (ES6), 35 bajtów
źródło
Idris , 204 bajty
Wypróbuj online!
Brzmi jak praca dla typów zależnych! Być może.
C jest funkcją typu curry. Biorąc pod uwagę wektor typów a = [t 1 , t 2 ,… t n ] i funkcję typu T: HVect a → Type , zwraca nowy typ:
Tutaj HVect jest heterogenicznym typem wektora z Idris Prelude - typ n pary, której elementy są n różnych typów.
C jest funkcją, która przyjmuje się i T kalkulacyjne argumentów, a następnie przekształca uncurried funkcję
f
typu ((B: HVect a) → Tb) w curry jednego typu C T .( C po prostu opisuje to, co chcemy zrobić; c faktycznie to robi. Ale nie możemy uciec od braku definicji C , ponieważ Idris wymaga, aby każda definicja najwyższego poziomu miała podpis typu).
Łącze TIO podaje przykład użycia. Jeśli zdefiniujemy funkcję dla 3-krotek (Nat, Nat, String) w następujący sposób:
następnie
uncurried [3, 4, "th"]
daje taki sam wynik jakc uncurried 3 4 "th"
. Idris wysuwa argumentya=[Nat, Nat, String]
iT=const String
, jak sądzę, dla nas.Oparłem ten kod na tej treści autorstwa timjb.
źródło
HVect
domyślnie -HVect
jest to w zasadzie krotka, którą można rozszyfrować.Python 3 ,
5453 bajtówWypróbuj online!
źródło
R , 96 bajtów
Wypróbuj online!
Poprzednia wersja (97 bajtów)
-1 bajt dzięki @JayCE
źródło
Kokos , 54 bajty
Wypróbuj online!
Kokos , 40 bajtów
Odpowiedź portu Python Erika .
Wypróbuj online!
źródło
Python 2 , 60 bajtów
Wypróbuj online!
Stopka to tester, który używa STDIN w następujący sposób w wierszu:
[a,b,...]
)Zauważ, że chociaż lista argumentów jest podawana jako dane wejściowe w testerze, w rzeczywistości curry ekwiwalent jest dodawany do listy, a lista jest zmniejszana przez wywołanie funkcji.
Podobna 55-bajtowa wersja została uprzejmie dostarczona przez ovs :
Wypróbuj online!
źródło
Kalafior , 84 bajtów
Wypróbuj online!
źródło
Perl 6 ,
4240 bajtówWypróbuj online!
-2 bajty dzięki Brad Gilbert b2gills .
źródło
*
, jest to konieczne tylko wtedy, gdy po nim jest coś takiego.assuming(*,1)
.Python 2 , 78 bajtów
Wypróbuj online!
źródło
Attache , 5 bajtów
Wypróbuj online!
Prosty wbudowany, w dużej mierze nieciekawy. Ale oto wersja od podstaw:
Attache, 35 bajtów
Wyjaśnienie:
źródło
Java 8, 46 + 318 = 364 bajtów
Jest to lambda curry (hah) przyjmująca funkcję i argument liczący i zwracająca funkcję curled.
Wypróbuj online
Rodzaj zgłoszenia
Funkcja wprowadzania
Dane wejściowe funkcji to obiekt z jedną metodą (wyłączając metody dziedziczone) reprezentującą funkcję. Należy pamiętać, że standardowy typ funkcjonalny interfejs nie może być używany jako typ danych wejściowych, ponieważ muszą być obsługiwane funkcje (np.) 3 parametrów. Należy również zauważyć, że wyrażenie lambda rzutowane na
java.util.function.Function
typ podobny do standardowego może zostać przekazane (metoda pojedyncza toapply
).Sprawdzone wyjątki mogą zostać zadeklarowane w funkcji wejściowej, ale nie mogą zostać wyrzucone (tzn. Nie zostaną propagowane do osoby wywołującej funkcję wyjściową). Przyjmuje się, że jest to do przyjęcia, ponieważ interfejsy funkcjonalne Javy nie zezwalają na sprawdzone wyjątki (a ich rozpowszechnienie zapobiegnie zwrotowi a
Function
). Propagowane są wyjątki czasu wykonywania (przypisywane doRuntimeException
lubError
).Funkcja wyjściowa
Wynik przedłożenia jest
java.util.function.Function<Object, Object>
. Zastanawiałem się nad zwróceniem zwykłegoObject
za pomocąapply
metody (jak na wejściu), ale wtedy konieczne będzie odbicie, aby wywołać wynik, który wydawał się wystarczająco niewygodny, aby był niedopuszczalny - w szczególności wywołanie do końca nie byłoby możliwe w jednym wyrażenie.Stosowanie
Ponieważ przesyłanie zwraca funkcję od
Object
doObject
, dane wyjściowe mogą być wywoływane bezpośrednio (za pomocąapply
), ale kolejne pośrednie wartości zwracane muszą być rzutowane na odpowiedni typ (np.java.util.function.Function<Object, Object>
) Przed wywołaniem. Zobacz przykłady użycia w TIO.Zauważ, że funkcje Java (tj. Metody) nie są obiektami pierwszej klasy. W związku z tym składnia użyta w wypunkcie wyjściowym opisu wyzwania nie ma znaczenia w Javie. Zamiast
f(a1, a2, a3)
tego mamyf.apply(a1, a2, a3)
, a nief(a1)(a2)(a3)
mamyf.apply(a1).apply(a2).apply(a3)
.Ograniczenia
Gdy zastosowany zostanie wynik pośredni (dodany argument), wynik jest faktycznie zmutowaną kopią oryginalnego wyniku. Na przykład w tym fragmencie:
linia 4 zostanie wydrukowana
4
, ale linia 5 nie powiedzie się, ponieważ do tego czasuc2
już zawiera argumenty2
i2
(zauważ też, żec2 == c
). Narusza to ducha curry, ale spełnia określone wymagania określone w wyzwaniu.Nie golfił
Zobacz TIO, aby uzyskać nie golfową kopię.
źródło
Julia 0.6 , 48 bajtów
Wypróbuj online!
Port odpowiedzi @ EricTheOutgolfer w Pythonie.
źródło
APL (Dyalog Classic) ,
5857 bajtówWypróbuj online!
Wywołanie składni (z funkcją curry
g
, argumentamix1
przezx3
i liczbą argumentówn
):((n x1 f g) x2) x3
Wymaga
⎕IO←1
źródło