Llamada por valor vs Llamada por nombre en Scala
- Llamada por valor en Scala
- Llamar por nombre en Scala
- Estrategias de llamada por valor frente a llamadas por nombre en Scala
- Conclusión
En este artículo, aprenderemos sobre las funciones de llamada por valor y llamada por nombre y sus estrategias de evaluación en Scala. Y discutiremos cómo usarlos en la práctica.
Llamada por valor en Scala
Los argumentos de función en Scala se consideran, de forma predeterminada, llamada por valor. Veamos un pequeño ejemplo:
def example(x:Int) = x*x
En el código anterior, hemos definido una función ejemplo
que toma un argumento como una llamada por valor.
Generalmente, al igual que los operadores en Scala, el compilador evalúa las funciones parametrizadas de la misma manera. Primero, todos los argumentos de la función se evalúan de izquierda a derecha; luego, todas las aplicaciones de función se reemplazan por el lado derecho de la función.
Simultáneamente, todos los parámetros formales de la función son reemplazados por los parámetros reales.
Una gran ventaja de la estrategia de llamada por valor es que cada argumento de función se evalúa solo una vez.
Llamar por nombre en Scala
Solo anteponemos =>
(igual y mayor que el símbolo) a los argumentos de la función para hacer que el argumento se llame por su nombre.
Veamos un pequeño ejemplo para entenderlo mejor:
def example(x: =>Int) = x*x
El parámetro x
en el código anterior se llama por valor. Aunque la evaluación de llamada por nombre es la misma que la estrategia de llamada por valor, tiene una gran ventaja: la función no se evaluará hasta que su valor correspondiente se use dentro del cuerpo de la función.
Estrategias de llamada por valor frente a llamadas por nombre en Scala
Digamos que tenemos una función add
con dos parámetros: x
, que es de tipo int y se llama por valor, e y
, que es de tipo int y se llama por nombre.
def add(x: Int, y:=>Int) = x+x
Veamos cómo se evalúa la función sumar
usando la estrategia call-by-value.
assert(add(3+3,8) == 12)
Aquí, la llamada por valor primero evalúa la expresión 3+3
y luego pasa el valor 6
al cuerpo de la función. El parámetro x
se suma a sí mismo para calcular la respuesta final como 12
.
Ahora, veamos la misma función evaluada usando la estrategia de llamada por nombre.
assert(add(8,3+3) == 16)
En este caso, la estrategia de llamada por nombre ignora 3+3
porque el parámetro y
nunca se usa dentro del cuerpo de la función. Por lo tanto, la x
se suma a sí misma para calcular la respuesta final como 16
.
Podemos decir que la estrategia de llamada por nombre es un poco más rápida que la estrategia de llamada por valor en este caso.
Veamos un ejemplo más, donde tenemos una función que recursivamente se llama a sí misma infinitamente.
def myFun(): Int = myFun() + 1
Ahora, si usamos esta función como parámetro x
en nuestra función agregar
, entonces el argumento llamada por valor
x
dará StackOverflowError
.
assertThrows[StackOverflowError]
{
add(myFun(),5)
}
En el código anterior, llamar a la función da StackOverflowError
porque el método myFun()
se evalúa antes que el cuerpo de la función. Por el contrario, si usamos el método myFun
como argumento de llamada por nombre, la llamada a la función se ejecuta correctamente sin generar ninguna excepción porque nunca se evaluará dentro del cuerpo de la función.
assert(add(5, myFun()) == 10)
el mejor para usar en nuestro código
Según los ejemplos anteriores, la estrategia de llamada por nombre parece más atractiva, ya que es más eficiente, ya que existen posibilidades de que el argumento pasado nunca se evalúe dentro del cuerpo de la función.
Pero, si lo vemos de manera holística, la estrategia de llamada por valor es más eficiente que la llamada por nombre, ya que en ella se evita el cálculo repetido de argumentos. Además, los efectos secundarios se pueden evitar ya que sabemos cuándo se evaluarán los argumentos en el código.
Conclusión
En este artículo, aprendimos sobre las estrategias de llamada por nombre y llamada por valor de Scala. Hemos aprendido cómo se evalúan y hemos visto su uso, y llegamos a la conclusión de que la estrategia de llamada por valor es mejor para usar en la mayoría de los casos.