Expresiones

Anuncio
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Lenguajes de Programación I
Control de Flujo - Expresiones
Ernesto Hernández-Novich
<emhn@usb.ve>
c 2006-2010
Copyright Control de Flujo
Expresiones
Consideraciones de Eficiencia
Definición
El Control de Flujo es fundamental para la mayoría de los
modelos de cómputo, pues establece el orden en que debe
ejecutarse el programa.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Organización de los Mecanismos
Secuenciación (Sequencing): orden específico,
usualmente el de aparición en el programa.
Selección (Selection): se escoje entre dos o más
instrucciones según alguna condición a tiempo de
ejecución.
Iteración (Iteration): un fragmento de código se ejecuta
de manera repetida bien sea un número de veces o hasta
cumplirse determinada condición a tiempo de ejecución.
Abstracción procedimental (Procedural Abstraction):
una colección de construcciones de control se encapsula
como una unidad, sujeta a parametrización.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Organización de los Mecanismos
Recursión (Recursion): una expresión se define en
términos de si misma directa o indirectamente.
Concurrencia (Concurrency): dos o más fragmentos de
programa se ejecutan/evalúan al mismo tiempo.
No determinismo (Nondeterminacy): el orden o
escogencia de instrucciones y expresiones no es
especificado deliberadamente.
Dejaremos los Procedimientos y la Concurrencia
para más adelante.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Expresiones
Una expresión puede ser:
Un objeto simple – nombre de variable o constante literal.
La aplicación de una función u operador a una colección de
argumentos u operandos, cada uno de los cuales es a su
vez una expresión.
El término operador se usa para referirse a las funciones
incluídas en el lenguaje que tienen una sintaxis especial
simplificada a propósito – + en lugar de “la función suma”.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Notación
Prefija (Scheme, LISP)
(+ (* 4 3) (* 0.5 (sin pi)))
Infija (casi cualquier lenguaje)
4 * 3 + 0.5 * sin(pi)
Postfija (Forth, Postscript)
4 3 * pi sin 0.5 * +
Mezclada (mixfix, Smalltalk)
msg sendTo: "emhn@usb.ve" text: "Hola Mundo"
En ocasiones los operadores son adornos (sintactic sugar)
sobre funciones concretas – en C++ a + b en realidad es
a.operator+(b).
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Precedencia y Asociatividad
La notación infija es ambigua para las expresiones
aritméticas.
Utilizar paréntesis para indicar explícitamente el orden de
evaluación.
Emplear reglas de precedencia y asociatividad para
ahorrarse los paréntesis (siempre que se haya leído el
manual).
Precedencia – en ausencia de paréntesis, ¿cuál operador
opera antes que otro?
Asociatividad – en ausencia de paréntesis, ¿cómo aplicar
los operadores de una secuencia en la cual todos tienen la
misma precedencia?
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Operadores Inusuales
Incremento y decremento pre y postfijos.
En vez de a = a + 1, escribir a++.
El efecto de borde siempre se efectúa – el valor cambia
según la posición del operador.
Producto de enteros por colecciones (cadenas, listas, . . . )
$a = $n x "a"; # $a tiene $n aes.
@b = (42) x 1; # Una lista con 42 unos.
@b = (42) x @b; # Ahora son 42 42.
Generadores de listas por enumeración
@a = -10..10;
Operador ternario if-then-else
a = (b > c) ? d : e
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Más operadores inusuales
Algunos lenguajes (Haskell, Prolog) permiten crear nuevos
operadores.
Asociados a una función particular.
Incorporados a la jerarquía de precedencia y asociatividad
para cooperar con el resto del lenguaje.
“Suma y producto de tuplas numéricas” en Haskell
infixl 5 :+:
infixl 7 :*:
(:+:), (:*:) :: (Num a,Num b) =>
(a,b) -> (a,b) -> (a,b)
(a1,b1) :+: (a2,b2) = (a1+a2,b1+b2)
(a1,b1) :*: (a2,b2) = (a1*a2,b1*b2)
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Un lenguaje lleno de operadores inusuales
IBM “engendró” APL – lenguaje puramente funcional.
Lleno de operadores funcionales aplicativos . . .
Generar la lista de primos de 1 hasta N
(∼ N ∈ N ◦ . × N)/N ← 1 ↓ ιN
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Un lenguaje lleno de operadores inusuales
IBM “engendró” APL – lenguaje puramente funcional.
Lleno de operadores funcionales aplicativos . . .
Generar la lista de primos de 1 hasta N
(∼ N ∈ N ◦ . × N)/N ← 1 ↓ ιN
. . . pero requiriendo un teclado especial
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Asignación
Si una instrucción de cómputo influye en los cómputos que
le siguen más allá de retornar un valor simple, se dice que
tiene un efecto de borde o colateral (side effects).
En los lenguajes puramente funcionales (Haskell) no
existen los efectos de borde y se dice que tienen
transparencia referencial.
Asignar un valor a un símbolo sólo lo hace disponible
durante la evaluación actual.
Solamente hay valores que producen valores por
aplicación funcional.
En los lenguajes imperativos, los efectos de borde son la
norma – modificar el estado es lo que produce resultados.
Asignar un valor a un símbolo lo hace disponible durante la
evaluación actual y posiblemente más allá de ella.
Existen valores y referencias a valores.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Valores vs. Referencias
La dualidad existencial de las variables
En los lenguajes imperativos los nombres de variable
denotan “contenedores” para valores.
Los roles del lado derecho e izquierdo son diferentes en
una asignación cualquiera:
El lado derecho debe producir un valor.
El lado izquierdo debe referir una ubicación.
Las expresiones que denotan valores se denominan
r-values y las expresiones que denotan ubicaciones se
denominan l-values.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
l-values vs. r-values
Algunas expresiones no pueden ser l-values
2 + 3 = a, no tiene sentido.
a = 2 + 3, tampoco, cuando a es una constante.
Un l-value no tiene que ser necesariamente un nombre ni
tampoco simple
Aprovechando apuntadores
(f(a)+3)->b[c] = 2
El lenguaje permite funciones l-value
substr($a,5,4) = "hola mundo!"
El mismo objeto puede actuar como r-value o l-value en
una misma expresión – depende cuál atributo de la
asociación interesa.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Modelo de acceso para variables
En el Modelo de Valor, la variable puede considerarse un
r-value o l-value según aplique.
En el Modelo de Referencia, toda variable siempre es
considerada como un l-value.
Esto obliga a seguir la referencia (dereferencing) en los
casos en que sea necesario.
En la mayoría de lenguajes con ese modelo, eso es
automático; en algunos es responsabilidad del
programador.
Acarrea la incomodidad del encajonado (boxing) en
algunos lenguajes (Java).
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Ortogonalidad
Cuando las características del lenguaje pueden ser
utilizadas en cualquier combinación de manera
consistente, se dice que es ortogonal.
Lenguajes orientados a expresiones no distinguen
instrucción de expresión (Algol fue el primero).
begin
a := if b < c then d else e;
a := begin f(b); g(c) end;
g(d);
2 + 3;
end;
Lenguajes con una aproximación intermedia (como C,
Java, Perl) contemplan instrucciones con valor
(expression statements).
a = (b < c) ? d : e;
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Asignaciones Especiales
La asignación como una expresión.
a = b = 1;
$a = ($b = 5) * ($c = f($d) + 9);
Combinar un operador con una asignación.
a += 5;
b[8].a->b *= 2;
$str = "foo";
$str .= " bar";
Asignación múltiple
($a,$b) = (42, "hola");
($b,$a) = ($a,$b) # Look ma! No temp
($a,$b,$c) = foo(...);
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Inicialización de Variables
Proveer un valor inicial al momento de la declaración
reduce la posibilidad de errores difíciles de identificar.
Para variables con almacenamiento estático, el valor inicial
puede colocarse directamente a tiempo de compilación
ahorrando tiempo de ejecución.
Algunos lenguajes no tienen mecanismo de inicialización
especial, salvo asignar manualmente los valores.
Algunos lenguajes establecen reglas de inicialización
automática.
Los lenguajes orientados a objetos proveen
constructores a ser invocados durante la inicialización.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
¿Cuándo se evalúan los operandos?
a - f(b) - c * d
f(a,g(b),c)
Puede influir (bugs) si hay efectos colaterales.
Permite mejorar el código objeto. Es por esto que en la
mayoría de los lenguajes el orden de evaluación de
operandos no está definido.
Algunas excepciones:
Java y C# insisten en evaluar de izquierda a derecha.
C y C++ evalúan los argumentos para funciones de
derecha a izquierda.
Algunos compiladores de Fortran reordenar expresiones
según las propiedades matemáticas.
Control de Flujo
Expresiones
Consideraciones de Eficiencia
Corto circuito – Evaluación de McCarthy
Mínimo trabajo necesario para obtener el resultado
Las expresiones lógicas (boolean expressions) pueden
optimizarse para evitar la evaluación total
Una secuencia de or es cierta tan pronto una sea cierta.
Una secuencia de and es falsa tan pronto una sea falsa.
Algunos lenguajes (Pascal) no ofrecen evaluación con
cortocircuito.
Algunos lenguajes (Erlang) ofrecen ambas posibilidades,
vía operadores diferenciados.
and y or – no usan cortocircuito.
andalso y orelse – si usan cortocircuito.
Al emplear corto-circuito, dejan de ser estrictas – ya no
son expresiones sino instrucciones
Descargar