Últimamente me he sentido cada vez más frustrado porque en la mayoría de los lenguajes de programación modernos con los que he trabajado (C / C ++, C #, F #, Ruby, Python, JS y más) hay muy poco, si es que hay alguno, soporte de lenguaje para determinar qué una subrutina realmente servirá.
Considere el siguiente pseudocódigo simple:
var x = DoSomethingWith(y);
¿Cómo determino qué hará realmente la llamada a DoSomethingWith (y) ? ¿Mutará y , o devolverá una copia de y ? ¿Depende del estado global o local, o solo depende de y ? ¿Cambiará el estado global o local? ¿Cómo afecta el cierre el resultado de la llamada?
En todos los idiomas que he encontrado, casi ninguna de estas preguntas se puede responder simplemente mirando la firma de la subrutina, y casi nunca hay soporte en tiempo de compilación o tiempo de ejecución. Por lo general, la única forma es confiar en el autor de la API y esperar que la documentación y / o las convenciones de nomenclatura revelen lo que realmente hará la subrutina.
Mi pregunta es la siguiente: ¿Existe algún lenguaje hoy en día que haga distinciones simbólicas entre este tipo de escenarios y ponga restricciones de tiempo de compilación sobre qué código puede escribir realmente?
(Por supuesto, hay algo de apoyo para esto en la mayoría de los lenguajes modernos, como diferentes niveles de alcance y cierre, la separación entre código estático y de instancia, funciones lambda, etc.) Pero con demasiada frecuencia estos parecen entrar en conflicto entre sí. Por ejemplo, una función lambda generalmente será puramente funcional y simplemente devolverá un valor basado en parámetros de entrada, o mutará los parámetros de entrada de alguna manera, pero generalmente es posible acceder a variables estáticas desde una función lambda, que a su vez puede le da acceso a las variables de instancia, y luego todo se separa).
fuente
Respuestas:
Sí, quieres mirar a Haskell. Hace exactamente lo que quieres. Todas las funciones son puras por defecto y solo pueden mutar el estado usando Monads. También Haskell tiene garantías estáticas muy fuertes sobre todo tipo de cosas http://learnyouahaskell.com/
fuente
C y C ++ tienen soporte muy limitado para al menos parte del problema a través de la
const
palabra clave; Si bien esto por sí solo no controla la pureza, se puede usar (especialmente en C ++) para decirle al compilador que una estructura de datos en particular no se debe modificar a través de un puntero dado. Algunos compiladores (p. Ej., Gcc) también proporcionan un atributo "puro" como una extensión de lenguaje para imponer plenamente la pureza. (Ver esta pregunta para más detalles).El lenguaje de programación D tiene soporte para declarar explícitamente la pureza de las funciones, y los compiladores verificarán y aplicarán la pureza (es decir, tratar de llamar a una función no pura desde una función pura produce un error del compilador).
Haskell es completamente puro, es decir, el lenguaje en sí no puede expresar funciones impuras, y no existe el concepto de "rutina". Cualquier cosa que no pueda resolverse utilizando solo funciones puras se subcontrata al tiempo de ejecución (impuro); Un programa con efectos secundarios se implementa construyendo (utilizando construcciones exclusivamente puras) una estructura de datos diferida que describe el comportamiento del programa y luego entregándolo al tiempo de ejecución. La comunidad de Haskell está experimentando activamente con todo un zoológico de lenguajes de programación, algunos de ellos puros, otros con pureza explícita.
Puede haber más, pero estas son las que conozco.
fuente
Parece que Felix tiene tres categorías:
funciones
procedimientos
generadores
fuente