Mógłbym zapisać indeksy wielokąta w bieżącej scenie, indeks przeciągniętego punktu w wielokącie i zamieniać go za każdym razem. Ale to podejście nie jest skalowane - gdy poziomy składu wzrosną do 5 i dalej, płyta kotłowa stałaby się nie do zniesienia.
Masz całkowitą rację, to podejście nie jest skalowane, jeśli nie możesz obejść płyty kotła . W szczególności zmieniono płytę główną do tworzenia zupełnie nowej Sceny z małą podsekcją. Jednak wiele języków funkcjonalnych stanowi konstrukt do radzenia sobie z tego rodzaju manipulowaniem strukturami zagnieżdżonymi: soczewkami.
Soczewka jest zasadniczo narzędziem do pobierania i ustawiania niezmiennych danych. Obiektyw skupia się na niewielkiej części większej struktury. Biorąc pod uwagę soczewkę, są dwie rzeczy, które możesz z nią zrobić - możesz zobaczyć małą część wartości większej struktury lub możesz ustawić małą część wartości większej struktury na nową wartość. Załóżmy na przykład, że masz obiektyw, który skupia się na trzecim elemencie na liście:
thirdItemLens :: Lens [a] a
Ten typ oznacza, że większa struktura jest listą rzeczy, a mała podsekcja jest jedną z tych rzeczy. Biorąc pod uwagę ten obiektyw, możesz wyświetlić i ustawić trzeci element na liście:
> view thirdItemLens [1, 2, 3, 4, 5]
3
> set thirdItemLens 100 [1, 2, 3, 4, 5]
[1, 2, 100, 4, 5]
Powodem, dla którego soczewki są przydatne, jest to, że są to wartości reprezentujące metody pobierające i ustawiające, i można nad nimi streścić w taki sam sposób, jak inne wartości. Możesz tworzyć funkcje zwracające soczewki, na przykład listItemLens
funkcję, która pobiera liczbę n
i zwraca soczewkę wyświetlającą ten n
element na liście. Dodatkowo soczewki mogą być złożone :
> firstLens = listItemLens 0
> thirdLens = listItemLens 2
> firstOfThirdLens = lensCompose firstLens thirdLens
> view firstOfThirdLens [[1, 2], [3, 4], [5, 6], [7, 8]]
5
> set firstOfThirdLens 100 [[1, 2], [3, 4], [5, 6], [7, 8]]
[[1, 2], [3, 4], [100, 6], [7, 8]]
Każda soczewka zawiera zachowanie podczas przechodzenia przez jeden poziom struktury danych. Łącząc je, możesz wyeliminować płytę kotłową do przechodzenia przez wiele poziomów złożonych struktur. Załóżmy na przykład, że masz scenePolygonLens i
widok i
wielokąta w scenie i polygonPointLens n
widok nth
punktu w wielokącie, możesz stworzyć konstruktor soczewek, który skupia się na konkretnym punkcie, na którym ci zależy w całej scenie:
scenePointLens i n = lensCompose (polygonPointLens n) (scenePolygonLens i)
Załóżmy teraz, że użytkownik klika punkt 3 wielokąta 14 i przesuwa go o 10 pikseli w prawo. Możesz zaktualizować scenę w następujący sposób:
lens = scenePointLens 14 3
point = view lens currentScene
newPoint = movePoint 10 0 point
newScene = set lens newPoint currentScene
To ładnie zawiera całą podstawkę do przemierzania i aktualizowania Sceny w środku lens
, wszystko, o co musisz się martwić, to to, na co chcesz zmienić punkt. Możesz dodatkowo to wyodrębnić za pomocą lensTransform
funkcji, która akceptuje soczewkę, cel i funkcję aktualizowania widoku celu przez soczewkę:
lensTransform lens transformFunc target =
current = view lens target
new = transformFunc current
set lens new target
Pobiera to funkcję i zamienia ją w „aktualizator” w skomplikowanej strukturze danych, stosując funkcję tylko do widoku i używając go do budowy nowego widoku. Wracając do scenariusza przesunięcia trzeciego punktu 14. wielokąta w prawo o 10 pikseli, co można wyrazić w następujący lensTransform
sposób:
lens = scenePointLens 14 3
moveRightTen point = movePoint 10 0 point
newScene = lensTransform lens moveRightTen currentScene
I to wszystko, czego potrzebujesz, aby zaktualizować całą scenę. To bardzo skuteczny pomysł i działa bardzo dobrze, gdy masz jakieś fajne funkcje do konstruowania obiektywów wyświetlających fragmenty twoich danych, na których Ci zależy.
Jednak obecnie wszystko to jest dość popularne, nawet w społeczności programistów funkcjonalnych. Trudno jest znaleźć dobre wsparcie biblioteki do pracy z soczewkami, a jeszcze trudniej jest wyjaśnić, jak one działają i jakie są korzyści dla twoich współpracowników. Podejmij to podejście z odrobiną soli.