Aprendí a programar principalmente desde un punto de vista de OOP (como la mayoría de nosotros, estoy seguro), pero pasé mucho tiempo tratando de aprender a resolver problemas de manera funcional. Tengo una buena comprensión de cómo resolver problemas de cálculo con FP, pero cuando se trata de problemas más complicados, siempre me encuentro volviendo a necesitar objetos mutables. Por ejemplo, si estoy escribiendo un simulador de partículas, querré que se actualicen los "objetos" de partículas con una posición mutable. ¿Cómo se resuelven típicamente los problemas inherentemente "con estado" utilizando técnicas de programación funcional?
functional-programming
Andrew Martin
fuente
fuente
Respuestas:
Los programas funcionales manejan muy bien el estado, pero requieren una forma diferente de verlo. Para su ejemplo de posición, una cosa a considerar es que su posición sea una función del tiempo en lugar de un valor fijo . Esto funciona bien para partículas que siguen una ruta matemática fija, pero requiere una estrategia diferente para manejar un cambio en la ruta, como después de una colisión.
La estrategia básica aquí es crear funciones que tomen un estado y devuelvan el nuevo estado . Por lo tanto, un simulador de partículas sería una función que toma una
Set
de las partículas como entrada y devuelve una nuevaSet
de partículas después de un paso de tiempo. Luego, simplemente llama repetidamente a esa función con su entrada establecida en su resultado anterior.fuente
Como señaló @KarlBielefeldt, el enfoque funcional para tal problema es verlo como un nuevo estado de un estado anterior. Las funciones en sí no contienen ninguna información, por lo que siempre actualizarán el estado m al estado n .
Creo que esto le parece ineficiente porque supone que el estado anterior debe mantenerse en la memoria mientras se calcula el nuevo estado. Tenga en cuenta que la elección entre escribir un estado completamente nuevo o reescribir el antiguo en su lugar es un detalle de implementación desde el punto de vista de un lenguaje funcional.
Por ejemplo, supongamos que tengo una lista de un millón de enteros y quiero aumentar la décima en una unidad. Copiar toda la lista con un nuevo número en su décima posición es un desperdicio, tiene razón; pero es solo la forma conceptual de describir la operación al compilador o intérprete de lenguaje. El compilador o intérprete es libre de tomar la primera lista y simplemente sobrescribir la décima posición.
La ventaja de describir la operación de esta manera es que el compilador puede razonar sobre la situación en la que muchos hilos quieren actualizar la misma lista en diferentes posiciones. Si la operación se describe como "vaya a esta posición y sobrescriba lo que encuentre", entonces es el programador, no el compilador, quien se encarga de asegurarse de que las sobrescrituras no colisionen.
Dicho todo esto, incluso en Haskell hay una mónada estatal que ayuda a modelar situaciones en las que "mantener el estado" es una solución más intuitiva para un problema. Pero también tenga en cuenta que algunos problemas que encuentra " intrínsecamente con estado, como escribir en una base de datos " tienen soluciones inmutables como Datomic . Esto puede ser sorprendente hasta que comprenda que es un concepto, no necesariamente su realización.
fuente
Suscribirse al modelo mental correcto ayuda a pensar y gestionar mejor el estado. En mi opinión, el mejor modelo mental es el libro animado . Una vez que haga clic, comprenderá que FP se apoya fuertemente en estructuras de datos persistentes que capturan el estado del mundo y que las funciones se utilizan para hacer la transición de ese estado sin ninguna mutación.
Rich Hickey ilumina estas ideas:
Hay otras conversaciones, pero esto debería enviarlo en la dirección correcta.
fuente
Al escribir aplicaciones grandes y moderadamente grandes, a menudo he encontrado útil diferenciar entre las secciones de la aplicación que tienen estado y las que no tienen estado.
Las clases / estructuras de datos en la sección con estado almacenan los datos de la aplicación y las funciones en esta sección funcionan con conocimiento implícito de los datos de la aplicación.
Las clases / estructuras de datos / funciones en la sección sin estado están ahí para soportar los aspectos puramente algorítmicos de la aplicación. No tienen conocimiento implícito de los datos de la aplicación. Trabajan en una naturaleza puramente funcional. Las partes con estado de la aplicación pueden experimentar un cambio de estado como efecto secundario de las funciones en ejecución en la sección sin estado de la aplicación.
La parte más difícil es descubrir qué clases / funciones colocar en la sección sin estado y qué clases / funciones colocar en la sección con estado, y tener la disciplina para colocarlas en archivos / bibliotecas separadas.
fuente