En lenguajes imperativos, es trivial diseñar una prueba de programación del uso del lenguaje de "semántica de valor" o "semántica de referencia". Se podría hacer lo siguiente y verificar el valor de a
(where Vertex {one, two, three :: Integer}
):
a := Vertex 3 4 5
b := a
one b := 6
two b := 8
three b := 10
Sin embargo, dado que las variables son inmutables en lenguajes funcionales, esta prueba no funcionará en dichos lenguajes.
Sé muy poco sobre Haskell (y la programación funcional en general), pero entiendo que usa semántica de valor. ¿Es posible idear un experimento de programación que distinga entre un "registro de referencia" y un "registro val" en Haskell?
functional-programming
haskell
David Chouinard
fuente
fuente
a
"?Respuestas:
No existe tal prueba, porque, sin mutabilidad, la distinción no es significativa (como demostró).
fuente
IORef
,MVar
, etc.) son mutables y se comportan como referencias ( hpaste.org/81192 )Haskell no tiene referencias (una referencia es un objeto mutable y Haskell no tiene objetos mutables (directamente accesibles)). Por lo tanto, las llamadas a funciones usan semántica de valor, como por defecto. De hecho, esta es una propiedad importante de los lenguajes funcionales puros: una función no puede modificar su argumento.
La semántica del valor no implica que la copia ocurra debajo del capó. Solo necesita copiar la parte de un valor que la función modifica, lo que en un lenguaje puro significa que nunca necesita copiar nada.
Sin embargo, esta no es toda la historia. En cierto sentido, Haskell tiene semántica de referencia.
Si bien no tiene sentido probar si una función modifica su argumento (nunca lo hace), puede probar si una función usa (parte de) su argumento. Proporcione un argumento que no termine. Si la llamada a la función termina, usted sabe que la función no usó su argumento.
Si evalúa
bottom
, no termina: sebottom
expande a sí mismo, hasta la saciedad. El términobottom
no puede tener un valor. Pero si evalúaignore bottom
, el valor es1
. Esto muestra que llamar a la funciónignore
no requiere calcular el valor de su argumento. En este sentido, Haskell tiene una semántica de referencia: lo que recibe una función no es un valor, sino algo que permite encontrar este valor. El término técnico es llamar por nombre (en oposición a llamar por valor ).(Más precisamente, las implementaciones de Haskell usan llamada por necesidad . En llamada por valor, el argumento de una función se evalúa exactamente una vez, justo antes de llamar a la función. En llamada por nombre, el argumento se evalúa cada vez que se usa, lo que puede variar desde nunca hasta tantas veces como lo desee la función. En caso de necesidad, el argumento se evalúa como máximo una vez: se evalúa la primera vez que se usa, o nunca si no se usa).
fuente
Es imposible distinguir entre ellos. Lo que esto significa es que el compilador es libre de elegir usar la semántica que considere adecuada para un rendimiento óptimo.
En particular, los lenguajes funcionales se describen típicamente como que tienen una semántica de valor, porque eso coincide con nuestro modelo conceptual de ellos, pero a menudo se implementan usando semántica de referencia porque es más eficiente. (¡No es necesario copiar algo que no se puede cambiar!)
fuente