Evaluación de expresiones¶
Las expresiones se evalúan de izquierda a derecha, tomando en cuenta los operadores de precedencia.
scala> 1 + 2 + 3 + 4 + 5
val res2: Int = 15
// Evaluación: ((((1 + 2) + 3) + 4) + 5) = 15
scala> 3 + 3 + 4 + 5
val res3: Int = 15
// Evaluación: ((((3 + 3) + 4) + 5) = 15
scala> 6 + 4 + 5
val res4: Int = 15
// Evaluación: (((6 + 4) + 5) = 15
scala> 10 + 5
val res5: Int = 15
// Evaluación: (10 + 5) = 15
scala> 15
val res6: Int = 15
// Resultado final
Por ejemplo, la multiplicación tiene mayor precedencia que la suma, por lo que se ejecuta primero:
scala> 1+2*3
val res7: Int = 7
// Evaluación: 1 + (2 * 3) = 1 + 6 = 7
scala> (1+2)*3
val res8: Int = 9
// Evaluación: (1 + 2) * 3 = 3 * 3 = 9
En caso tal, usted puede especificar el orden de evaluación utilizando paréntesis para alterar la precedencia de operadores.
Funciones¶
Las funciones son valores que esperan otros valores (parámetros) y efectúan una operación sobre ellos. Ejemplo:
scala> def f(x:Int):Int = x+2*x*x
def f(x: Int): Int
// Definición de función que toma un parámetro entero x y retorna x + 2*x*x
scala> f
val res9: Int => Int = Lambda$1634/0x00007f22d8583940@27c243a3
// f es un valor de tipo función que toma un Int y retorna un Int
scala> f(10)
val res10: Int = 210
// Evaluación: 10 + 2*10*10 = 10 + 200 = 210
Estrategias de evaluación de expresiones¶
Una estrategia de evaluación es el método mediante el cual se reducen todas las expresiones a un valor final. Existen dos estrategias principales:
1. Evaluación por Valor (Call By Value - CBV)¶
En esta estrategia, los argumentos de una función se evalúan antes de pasar a la función. Esto significa que:
- Se evalúan todos los parámetros de izquierda a derecha
- Se evalúan todas las operaciones de izquierda a derecha
- Cada parámetro se evalúa exactamente una vez
Ventaja: Cada valor se evalúa solo una vez, lo que puede ser más eficiente cuando los parámetros se usan múltiples veces.
2. Evaluación por Nombre (Call By Name - CBN)¶
En esta estrategia, los argumentos se pasan sin evaluar y se evalúan solo cuando se usan dentro de la función. Esto significa que:
- Los parámetros se sustituyen directamente en el cuerpo de la función
- Se evalúan solo cuando se necesitan
- Un parámetro no usado nunca se evalúa
Ventaja: Si un parámetro no se usa en la función, no se realiza su evaluación, lo que ahorra cálculos innecesarios.
Ejemplo comparativo de estrategias¶
Consideremos la siguiente definición:
def test(x: Int, y: Int) = x*x
// Función que ignora el parámetro y y solo usa x
Caso 1: test(2, 3)¶
CBV (Evaluación por Valor):
// Paso 1: Evalúa 2 → 2
// Paso 2: Evalúa 3 → 3
// Paso 3: Aplica función: 2*2 → 4
// Total: 3 pasos
CBN (Evaluación por Nombre):
// Paso 1: Sustituye directamente: 2*2
// Paso 2: Evalúa: 2*2 → 4
// Total: 2 pasos
Resultado: CBN es más eficiente
Caso 2: test(3+4, 8)¶
CBV (Evaluación por Valor):
// Paso 1: Evalúa 3+4 → 7
// Paso 2: Evalúa 8 → 8
// Paso 3: Aplica función: 7*7 → 49
// Total: 3 pasos
CBN (Evaluación por Nombre):
// Paso 1: Sustituye directamente: (3+4)*(3+4)
// Paso 2: Evalúa primer (3+4) → 7*(3+4)
// Paso 3: Evalúa segundo (3+4) → 7*7
// Paso 4: Evalúa: 7*7 → 49
// Total: 4 pasos
Resultado: CBV es más eficiente. CBN realiza evaluaciones redundantes del parámetro x.
Caso 3: test(7, 2*4)¶
CBV (Evaluación por Valor):
// Paso 1: Evalúa 7 → 7
// Paso 2: Evalúa 2*4 → 8
// Paso 3: Aplica función: 7*7 → 49
// Total: 3 pasos
CBN (Evaluación por Nombre):
// Paso 1: Sustituye directamente: 7*7
// Paso 2: Evalúa: 7*7 → 49
// Total: 2 pasos
// Nota: El parámetro y (2*4) nunca se evalúa porque no se usa en la función
Resultado: CBN es más eficiente. El parámetro y no se utiliza, por lo que su evaluación es innecesaria.
Caso 4: test(3+4, 2*4)¶
CBV (Evaluación por Valor):
// Paso 1: Evalúa 3+4 → 7
// Paso 2: Evalúa 2*4 → 8
// Paso 3: Aplica función: 7*7 → 49
// Total: 3 pasos
CBN (Evaluación por Nombre):
// Paso 1: Sustituye directamente: (3+4)*(3+4)
// Paso 2: Evalúa primer (3+4) → 7*(3+4)
// Paso 3: Evalúa segundo (3+4) → 7*7
// Paso 4: Evalúa: 7*7 → 49
// Total: 4 pasos
// Nota: El parámetro y (2*4) nunca se evalúa, pero x se evalúa dos veces
Resultado: CBV es más eficiente
Tabla de resumen de conceptos¶
| Concepto | Descripción | Ventajas | Desventajas |
|---|---|---|---|
| Evaluación por Valor (CBV) | Los parámetros se evalúan antes de pasar a la función | Cada parámetro se evalúa una sola vez; más predecible | Parámetros no utilizados se evalúan innecesariamente |
| Evaluación por Nombre (CBN) | Los parámetros se sustituyen sin evaluar; se evalúan al usarse | Parámetros no usados no se evalúan; eficiente para valores costosos | Un parámetro usado múltiples veces se evalúa varias veces |
| Precedencia de operadores | Orden en que se ejecutan operaciones sin paréntesis explícitos | Multiplicación y división antes que suma y resta | Puede ser confuso sin paréntesis |
| Paréntesis | Alteran el orden de evaluación de expresiones | Permiten especificar explícitamente el orden deseado | Pueden hacer el código más verboso |
| Función | Valor que toma parámetros y realiza una operación | Reutilización de código; abstracción | Requiere comprensión de estrategias de evaluación |
Comentarios adicionales¶
-
En Scala, la evaluación por defecto es Call By Value (CBV). Sin embargo, es posible usar Call By Name (CBN) especificando el parámetro con
=>en la definición de la función. -
La elección entre CBV y CBN depende del contexto y del costo computacional de evaluar los parámetros. Para parámetros costosos, CBN puede ser más eficiente.
-
Algunos lenguajes como Haskell utilizan lazy evaluation (una forma de CBN optimizada) por defecto, lo que permite trabajar de manera eficiente incluso con estructuras de datos infinitas.
-
El concepto de reducción es fundamental en la evaluación de expresiones. Una reducción es un paso que reemplaza una subexpresión por su valor equivalente.
-
La asociatividad de los operadores también es importante: el operador
+es asociativo hacia la izquierda, por lo que1 + 2 + 3se evalúa como(1 + 2) + 3, no como1 + (2 + 3). -
En el análisis de eficiencia, se cuenta el número de pasos de reducción, no el tiempo real, para hacer las comparaciones independientes del hardware.