Chyba jeszcze nie żałowałem curry. Rozumiem, co to robi i jak to zrobić. Po prostu nie mogę wymyślić sytuacji, w której bym go użył.
Gdzie używasz curry w JavaScript (lub gdzie używają go główne biblioteki)? Mile widziane są przykłady manipulacji DOM lub ogólnych przykładów programowania aplikacji.
Jedna z odpowiedzi wspomina o animacji. Funkcje takie jak slideUp
, fadeIn
pobierają element jako argument i zwykle są funkcją curried zwracającą funkcję wyższego rzędu z domyślną wbudowaną funkcją animacji. Dlaczego jest to lepsze niż tylko stosowanie funkcji wyższego poziomu z niektórymi domyślnymi ustawieniami?
Czy są jakieś wady korzystania z niego?
Zgodnie z prośbą, oto kilka dobrych zasobów na temat curry JavaScript:
- http://www.dustindiaz.com/javascript-curry/
- Crockford, Douglas (2008) JavaScript: Dobre części
- http://www.svendtofte.com/code/curried_javascript/ (Objazd w ML, więc pomiń całą sekcję „Szybki kurs w ML” i zacznij od nowa od „Jak pisać curried JavaScript”)
- http://web.archive.org/web/20111217011630/http://blog.morrisjohns.com:80/javascript_closures_for_dummies
- Jak działają zamknięcia JavaScript?
- http://ejohn.org/blog/partial-functions-in-javascript (Mr. Resig o pieniądzach jak zwykle)
- http://benalman.com/news/2010/09/partial-application-in-javascript/
Dodam więcej, gdy pojawią się w komentarzach.
Tak więc, zgodnie z odpowiedziami, curry i ogólnie częściowe stosowanie są wygodnymi technikami.
Jeśli często „udoskonalasz” funkcję wysokiego poziomu, wywołując ją z tą samą konfiguracją, możesz użyć funkcji wyższego poziomu (lub użyć częściowej Resiga), aby utworzyć proste, zwięzłe metody pomocnicze.
źródło
svendtofte.com
wygląda na martwą - znaleziono go na maszynie WayBack pod adresem web.archive.org/web/20130616230053/http://www.svendtofte.com/ ... Przepraszamy, blog.morrisjohns.com/javascript_closures_for_dummies wydaje się być niedostępny teżOdpowiedzi:
@Hank Gay
W odpowiedzi na komentarz EmbiggensTheMind:
Nie przychodzi mi do głowy przypadek, w którym curry - samo w sobie - byłoby przydatne w JavaScript; jest to technika konwersji wywołań funkcji z wieloma argumentami do łańcuchów wywołań funkcji z jednym argumentem dla każdego wywołania, ale JavaScript obsługuje wiele argumentów w jednym wywołaniu funkcji.
W JavaScript - i zakładam, że większość innych rzeczywistych języków (nie rachunek lambda) - jest jednak powszechnie kojarzona z częściowym zastosowaniem. John Resig wyjaśnia to lepiej , ale istota jest taka, że ma pewną logikę, która zostanie zastosowana do dwóch lub więcej argumentów, a znasz tylko wartości niektórych z tych argumentów.
Możesz użyć częściowej aplikacji / currying, aby naprawić te znane wartości i zwrócić funkcję, która akceptuje tylko niewiadome, do wywołania później, gdy faktycznie masz wartości, które chcesz przekazać. Zapewnia to sprytny sposób na uniknięcie powtarzania się, gdy w kółko wywoływałbyś te same wbudowane funkcje JavaScript z tymi samymi wartościami z wyjątkiem jednej. Aby ukraść przykład Johna:
źródło
Oto interesujące I praktyczne zastosowanie curry w JavaScript, które używa domknięć :
Opiera się to na
curry
rozszerzeniuFunction
, chociaż jak widać, używa tylkoapply
(nic nadzwyczajnego):źródło
offset+input
będzieundefined + 1.60936
na twoimmilesToKm
przykładzie; co skutkujeNaN
.Znalazłem funkcje, które przypominają Pythona
functools.partial
bardziej przydatne w JavaScript:Dlaczego chcesz go używać? Typowa sytuacja, w której chcesz tego użyć, ma miejsce, gdy chcesz powiązać
this
funkcję z wartością:Teraz, gdy wywoływane jest wywołanie zwrotne,
this
wskazuje naobj
. Jest to przydatne w sytuacjach zdarzeń lub w celu zaoszczędzenia miejsca, ponieważ zwykle skraca kod.Currying jest podobna do częściowej z tą różnicą, że funkcja, którą zwraca currying przyjmuje tylko jeden argument (o ile to rozumiem).
źródło
Zgadzanie się z Hankiem Gayiem - jest niezwykle przydatne w niektórych prawdziwych funkcjonalnych językach programowania - ponieważ jest to niezbędna część. Na przykład w Haskell po prostu nie możesz wziąć wielu parametrów do funkcji - nie możesz tego zrobić w czystym programowaniu funkcyjnym. Bierzesz jeden parametr na raz i rozbudowujesz swoją funkcję. W JavaScript jest to po prostu niepotrzebne, pomimo wymyślnych przykładów, takich jak „konwerter”. Oto ten sam kod konwertera, bez potrzeby curry:
Żałuję, że Douglas Crockford w „JavaScript: The Good Parts” nie wspomniał o historii i faktycznym wykorzystaniu curry niż o swoich bezmyślnych uwagach. Przez długi czas po przeczytaniu tego byłem zdumiony, aż zacząłem studiować programowanie funkcjonalne i zdałem sobie sprawę, że to stąd pochodzi.
Po dłuższym namyśle stwierdzam, że istnieje jeden ważny przypadek użycia curry w JavaScript: jeśli próbujesz pisać przy użyciu czystych technik programowania funkcjonalnego przy użyciu JavaScript. Wydaje się jednak, że jest to rzadki przypadek użycia.
źródło
To nie jest żadna magia ani nic ... po prostu przyjemny skrót do anonimowych funkcji.
partial(alert, "FOO!")
jest równafunction(){alert("FOO!");}
partial(Math.max, 0)
koresponduje zfunction(x){return Math.max(0, x);}
Wywołania częściowe ( terminologia MochiKit . Myślę, że niektóre inne biblioteki nadają funkcjom metodę .curry, która robi to samo) wyglądają nieco ładniej i mniej hałaśliwie niż funkcje anonimowe.
źródło
Jeśli chodzi o biblioteki, które go używają, zawsze istnieje Functional .
Kiedy jest przydatny w JS? Prawdopodobnie w tym samym czasie jest przydatny w innych współczesnych językach, ale jedyny raz, kiedy go używam, to w połączeniu z częściowym zastosowaniem.
źródło
Powiedziałbym, że najprawdopodobniej cała biblioteka animacji w JS używa curry. Zamiast przekazywania dla każdego wywołania zestawu elementów, na które ma to wpływ, i funkcji, opisującej, jak element powinien się zachowywać, do funkcji wyższego rzędu, która zapewni wszystkie czynności związane z synchronizacją, jest to ogólnie łatwiejsze dla klienta do wydania, ponieważ niektóre publiczne API funkcja taka jak "slideUp", "fadeIn", która przyjmuje tylko elementy jako argumenty, a które są po prostu jakąś funkcją curried zwracającą funkcję wyższego rzędu z wbudowaną domyślną funkcją animacji.
źródło
Oto przykład.
Instrumentuję kilka pól za pomocą JQuery, aby zobaczyć, co robią użytkownicy. Kod wygląda następująco:
(W przypadku użytkowników innych niż JQuery mówię, że za każdym razem, gdy kilka pól jest aktywowanych lub traconych, chcę wywołać funkcję trackActivity (). Mógłbym również użyć funkcji anonimowej, ale musiałbym ją zduplikować 4 razy, więc wyciągnąłem go i nadałem mu nazwę.)
Teraz okazuje się, że z jednym z tych pól trzeba postępować inaczej. Chciałbym móc przekazać parametr w jednym z tych wywołań do naszej infrastruktury śledzenia. Z curry mogę.
źródło
W innym języku funkcjonalnym funkcje JavaScript nazywane są lamda. Może być używany do tworzenia nowego interfejsu API (bardziej wydajnej lub złożonej funkcji) w oparciu o proste dane wejściowe innego programisty. Curry to tylko jedna z technik. Możesz go użyć do utworzenia uproszczonego interfejsu API w celu wywołania złożonego interfejsu API. Jeśli jesteś programistą, który używa uproszczonego interfejsu API (na przykład używasz jQuery do wykonywania prostych operacji), nie musisz używać curry. Ale jeśli chcesz stworzyć uproszczone API, curry jest twoim przyjacielem. Musisz napisać framework javascript (jak jQuery, mootools) lub bibliotekę, wtedy możesz docenić jego moc. Napisałem ulepszoną funkcję curry o godz http://blog.semanticsworks.com/2011/03/enhanced-curry-method.html. Nie potrzebujesz metody curry, aby robić curry, po prostu pomaga to robić, ale zawsze możesz to zrobić ręcznie, pisząc funkcję A () {}, aby zwrócić inną funkcję B () {}. Aby było ciekawiej, użyj funkcji B (), aby zwrócić inną funkcję C ().
źródło
Znam jego stary wątek, ale będę musiał pokazać, jak jest używany w bibliotekach javascript:
Wykorzystam bibliotekę lodash.js, aby konkretnie opisać te koncepcje.
Przykład:
Częściowe zastosowanie:
Curry:
Wiążący:
stosowanie:
różnica:
po curry otrzymujemy nową funkcję bez żadnych parametrów.
po częściowym zastosowaniu otrzymujemy funkcję, która jest związana z pewnymi parametrami.
w powiązaniu możemy powiązać kontekst, który zostanie użyty do zastąpienia 'this', jeśli nie jest powiązany, domyślną funkcją będzie zasięg okna.
Porada: nie ma potrzeby odkrywania na nowo koła. Częściowe zastosowanie / wiązanie / curry są bardzo powiązane. Różnicę widać powyżej. Używaj tego znaczenia wszędzie, a ludzie rozpoznają, co robisz, bez problemów ze zrozumieniem, a ponadto będziesz musiał używać mniej kodu.
źródło
Zgadzam się, że czasami chciałbyś wprawić w ruch, tworząc pseudo-funkcję, która zawsze będzie miała wypełnioną wartość pierwszego argumentu. Na szczęście trafiłem na zupełnie nową bibliotekę JavaScript o nazwie jPaq (h ttp: // jpaq.org/ ), który udostępnia tę funkcję. Najlepszą rzeczą w bibliotece jest to, że możesz pobrać własną kompilację, która zawiera tylko potrzebny kod.
źródło
Właśnie napisałem przykład jPaq, który pokazuje kilka fajnych zastosowań funkcji curry. Sprawdź to tutaj: Currying Up String Functions
źródło
Chciałem tylko dodać trochę zasobów dla Functional.js:
Wykład / konferencja wyjaśniająca niektóre aplikacje http://www.youtube.com/watch?v=HAcN3JyQoyY
Zaktualizowana biblioteka Functional.js: https://github.com/loop-recur/FunctionalJS Kilku fajnych pomocników (przepraszam, nowa tutaj, brak reputacji: p): / loop-recur / PreludeJS
Ostatnio często używam tej biblioteki, aby zmniejszyć liczbę powtórzeń w bibliotece pomocniczej klientów IRC js. To świetna rzecz - naprawdę pomaga oczyścić i uprościć kod.
Ponadto, jeśli wydajność stanie się problemem (ale ta biblioteka jest dość lekka), łatwo jest po prostu przepisać za pomocą funkcji natywnej.
źródło
Możesz użyć natywnego wiązania do szybkiego rozwiązania w jednej linii
źródło
Kolejne uderzenie w to, od pracy z obietnicami.
(Uwaga: JS noob, pochodzący ze świata Pythona. Nawet tam curry nie jest używane zbyt często, ale czasami może się przydać. Więc połączyłem funkcję curry - zobacz linki)
Najpierw zaczynam od wywołania Ajax. Muszę wykonać pewne określone czynności w przypadku sukcesu, ale w przypadku niepowodzenia chcę tylko dać użytkownikowi informację zwrotną, że wywołanie czegoś spowodowało jakiś błąd . W moim rzeczywistym kodzie wyświetlam informacje o błędzie w panelu ładowania początkowego, ale używam tutaj tylko logowania.
Zmodyfikowałem mój adres URL na żywo, aby to się nie udało.
Teraz, aby poinformować użytkownika, że partia nie powiodła się, muszę zapisać tę informację w module obsługi błędów, ponieważ wszystko, co otrzymuje, to odpowiedź z serwera.
Wciąż mam informacje dostępne tylko w czasie kodowania - w moim przypadku mam kilka możliwych partii, ale nie wiem, która z nich nie powiodła się, analizując odpowiedź serwera o nieudanym adresie URL.
Zróbmy to. Dane wyjściowe konsoli to:
konsola:
bad batch run, dude utility.js (line 109) response.status:404
Teraz zmieńmy trochę rzeczy i użyj ogólnej procedury obsługi błędów wielokrotnego użytku, ale także takiej, która jest pobierana w czasie wykonywania z zarówno kontekstem wywołania znanego w czasie kodu, jak i informacjami w czasie wykonywania dostępnymi ze zdarzenia.
konsola:
Object { user_msg="bad batch run, dude. you were calling :Run ACL now"} utility.js (line 117) response.status:404 utility.js (line 118)
Mówiąc bardziej ogólnie, biorąc pod uwagę, jak powszechne jest użycie wywołań zwrotnych w JS, currying wydaje się być całkiem przydatnym narzędziem.
https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/ http://www.drdobbs.com/open-source/currying-and-partial-functions-in- javasc / 231001821? pgno = 2
źródło