Podría haber almacenado índices de Polígono en la escena actual, índice del punto arrastrado en Polígono y reemplazarlo cada vez. Pero este enfoque no escala: cuando los niveles de composición van a 5 y más, la repetitiva se volvería insoportable.
Tienes toda la razón, este enfoque no se escala si no puedes evitar la barrera . Específicamente, se modificó la plantilla para crear una escena completamente nueva con una pequeña subparte. Sin embargo, muchos lenguajes funcionales proporcionan una construcción para lidiar con este tipo de manipulación de estructuras anidadas: lentes.
Una lente es básicamente un captador y configurador de datos inmutables. Una lente se centra en una pequeña parte de una estructura más grande. Dada una lente, hay dos cosas que puede hacer con ella: puede ver la pequeña parte de un valor de la estructura más grande, o puede establecer la pequeña parte de un valor de una estructura más grande en un nuevo valor. Por ejemplo, suponga que tiene una lente que se enfoca en el tercer elemento de una lista:
thirdItemLens :: Lens [a] a
Ese tipo significa que la estructura más grande es una lista de cosas, y la subparte pequeña es una de esas cosas. Dada esta lente, puede ver y configurar el tercer elemento de la lista:
> view thirdItemLens [1, 2, 3, 4, 5]
3
> set thirdItemLens 100 [1, 2, 3, 4, 5]
[1, 2, 100, 4, 5]
La razón por la que las lentes son útiles es porque son valores que representan captadores y definidores, y puede abstraerlos de la misma manera que lo hace con otros valores. Puede realizar funciones que devuelvan lentes, por ejemplo, una listItemLens
función que toma un número n
y devuelve una lente que visualiza el n
elemento en una lista. Además, las lentes se pueden componer :
> 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]]
Cada lente encapsula el comportamiento para atravesar un nivel de la estructura de datos. Al combinarlos, puede eliminar el repetitivo para atravesar múltiples niveles de estructuras complejas. Por ejemplo, suponiendo que tiene un scenePolygonLens i
que ve el i
Polígono en una Escena, y polygonPointLens n
que ve el nth
Punto en un Polígono, puede hacer un constructor de lentes para enfocarse solo en el punto específico que le interesa en una escena completa de esta manera:
scenePointLens i n = lensCompose (polygonPointLens n) (scenePolygonLens i)
Ahora suponga que un usuario hace clic en el punto 3 del polígono 14 y lo mueve 10 píxeles hacia la derecha. Puedes actualizar tu escena así:
lens = scenePointLens 14 3
point = view lens currentScene
newPoint = movePoint 10 0 point
newScene = set lens newPoint currentScene
Esto contiene muy bien toda la plantilla para atravesar y actualizar una escena en el interior lens
, todo lo que tiene que preocuparse es a qué desea cambiar el punto. Puede resumir esto con una lensTransform
función que acepta una lente, un objetivo y una función para actualizar la vista del objetivo a través de la lente:
lensTransform lens transformFunc target =
current = view lens target
new = transformFunc current
set lens new target
Esto toma una función y la convierte en un "actualizador" en una estructura de datos complicada, aplicando la función solo a la vista y usándola para construir una nueva vista. Volviendo al escenario de mover el 3er punto del polígono 14 a los 10 píxeles correctos, eso se puede expresar en términos de la siguiente lensTransform
manera:
lens = scenePointLens 14 3
moveRightTen point = movePoint 10 0 point
newScene = lensTransform lens moveRightTen currentScene
Y eso es todo lo que necesitas para actualizar toda la escena. Esta es una idea muy poderosa y funciona muy bien cuando tiene algunas funciones agradables para construir lentes que visualizan los datos que le interesan.
Sin embargo, todo esto es bastante interesante actualmente, incluso en la comunidad de programación funcional. Es difícil encontrar un buen soporte de biblioteca para trabajar con lentes, y aún más difícil explicar cómo funcionan y cuáles son los beneficios para sus compañeros de trabajo. Toma este enfoque con un grano de sal.