Wzorce interfejsu użytkownika w językach funkcjonalnych

11

Chciałbym zacząć bawić się w ClojureScript, ale zastanawiam się nad niektórymi punktami. Moim problemem jest to, co jest dobrym sposobem radzenia sobie ze zmianami stanu wynikającymi z interakcji użytkownika, gdy próbujesz funkcjonalnie pracować.

Podam kilka przykładów. Mam na myśli aplikacje działające w przeglądarce, ale myślę, że problem jest bardziej ogólny. Oczywiście coś się zmieni - przynajmniej DOM. Chciałbym jednak dowiedzieć się, jak zorganizować resztę kodu do pracy z niezmiennymi strukturami danych.

1) Powiedzmy, że chcę dołączyć pewne zdarzenia do jakiegoś obiektu DOM. Nie jest to trudne w przeważnie funkcjonalny sposób: kiedy tworzysz węzeł, dołączasz do niego mapę skrótu z różnymi modułami obsługi zdarzeń. Ale rozważ przypadek, w którym używasz delegowania zdarzeń. Następnie, gdy tworzysz nowy węzeł, możesz dołączyć moduł obsługi zdarzeń do jakiegoś węzła nadrzędnego, który prawdopodobnie już istnieje. Musisz więc zmienić skrót powiązany z już istniejącym węzłem.

2) Powiedzmy, że projektuję moduł autouzupełniania dla pola wejściowego. Za każdym razem, gdy użytkownik naciska klawisz, mogę zadzwonić do serwera, aby uzyskać sugestie. To jest łatwe. Ale teraz załóżmy, że chcę to trochę zoptymalizować. Jeśli znam wszystkie pasujące wyniki, foonie ma sensu pytać ponownie o wszystkie pasujące wyniki foobar; Mogę po prostu odfiltrować to pierwsze. Muszę więc zbudować pamięć podręczną. Ta pamięć podręczna będzie aktualizowana za każdym razem, gdy użytkownik wstawi nowe słowo, które nie jest nadzbiorem wcześniej wprowadzonych słów. Znowu: jak modelować pamięć podręczną? Najbardziej rozsądnym sposobem wydaje się być mapa haszująca odwzorowująca słowa na wyniki, ale powinna być zmienna.

Czy możesz zasugerować pewne wzorce, które ułatwiłyby uwzględnienie zmian wynikających z interakcji użytkownika w funkcjonalnym projekcie?

Andrea
źródło
4
Wyszukaj „Funkcjonalne programowanie reaktywne”.
dan_waterworth
To nie jest dokładnie to samo, ale z (bez efektów ubocznych) szablonami XSLT, które pasują do zdarzeń DOM zainicjowanych przez użytkownika, mamy podobny problem w Saxon-CE. Podoba mi się to, że użytkownik wywołuje zmianę stanu, a nie XSLT, więc to trochę OK. Kluczem jest upewnienie się, że kod zarządzający interakcją użytkownika i późniejszymi zmianami stanu jest bardzo oddzielny od reszty.
pgfearo
@pgfearo Czy masz jakieś porady, jak zorganizować kod, aby interakcja użytkownika była wystarczająco oddzielona od reszty?
Andrea
Nie ma dobrego sposobu radzenia sobie ze zmianami stanu, gdy pracujesz funkcjonalnie, ponieważ programowanie funkcjonalne jest bezstanowe.
Old Pro
3
@Old Pro: To nie jest całkowicie poprawne. Podczas gdy w programowaniu funkcjonalnym definiujesz obliczenia za pomocą aplikacji funkcji zamiast efektu ubocznego, ostatecznie musisz gdzieś zapisać wynik obliczeń. FP skupia się na ograniczeniu użycia stanu do minimum, podczas gdy w programowaniu imperatywnym przekształcanie stanu przyrostowo (przez efekty uboczne) jest podstawowym narzędziem do definiowania obliczeń.
Giorgio

Odpowiedzi:

3

Jak wspomniano w komentarzach, powinieneś poszukać „Funkcjonalnego programowania reaktywnego”, a także przeczytać niektóre posty na http://prog21.dadgum.com/archives.html . Mówiąc dokładniej, prawdopodobnie powinieneś przeczytać „ Nie zakochaj się w swojej technologii ”, „ Napisz kod, jak dopiero co nauczyłeś się programować ”, „ Programowanie funkcjonalne nie działa (i co z tym zrobić) ”, a może kilka innych.

Całkowite uniknięcie zmienności i skutków ubocznych jest praktycznie niemożliwe. Nawet programiści Haskell od czasu do czasu wykorzystają unsafePerformIOdo wyjścia z czysto funkcjonalnego, pozbawionego efektów ubocznych, statycznie wpisanego paradygmatu, aby zrobić pewne rzeczy. Jeśli podejmujesz ten projekt jako ćwiczenie czysto akademickie, kontynuuj i unikaj w jak największym stopniu zmienności i skutków ubocznych, ale jeśli próbujesz zbudować użyteczny produkt w terminie, żaden wzór cię nie uratuje.

davidk01
źródło