Cap. 5. Órdenes. Cap. 5. Órdenes. Índice del capı́tulo Capı́tulo 5. Órdenes Lenguajes de Programación Capı́tulo 5. Órdenes 1. Semántica denotacional de las órdenes 2. Órdenes elementales Carlos Ureña Almagro 3. Órdenes compuestas Dpt. Lenguajes y Sistemas Informáticos ETSI Informática y de Telecomunicación Universidad de Granada Curso 2009-10 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 1/1. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 2/1. Cap. 5. Órdenes. Semántica denotacional de las órdenes Semántica denotacional de las órdenes Indice de la sección Semántica denotacional Sección 1 Semántica denotacional de las órdenes Una orden es una construcción sintáctica que denota una función de transición entre estados de ejecución durante la ejecución de un programa. Por tanto, una orden es formalmente una aplicación del conjunto de los estados de ejecución en sı́ mismo Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 3/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 4/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Semántica denotacional de las órdenes Semántica denotacional de las órdenes Semántica de una orden Ejemplo: Supongamos la orden O siguiente: Efecto en el estado de ejecución Ejemplo: Supongamos el estado de ejecución S: S = { (”x”, f loat, 1.2) , (”peso”, int, 62) } peso = peso + 1 Esta orden se aplica a estados donde existe una variable de nombre ”peso”, de algún tipo entero, y produce estados donde esa variable vale uno más que en el original. Sea f la aplicación asociada a la orden O vista antes, se cumple que el estado T = f (S) (la imagen por f de S) es el siguiente: f (S) = { (”x”, f loat, 1.2) , (”peso”, int, 63) } Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 5/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 6/91. Cap. 5. Órdenes. Semántica denotacional de las órdenes Semántica denotacional de las órdenes Dominio de una orden Algunos estados de ejecución no pertenecen al dominio de algunas órdenes, por ejemplo, el estado siguiente: Finalización de una orden I Cuando la ejecución de una orden no termina (por ejemplo, la orden es un bucle infinito), también decimos que la ejecución falla, y por tanto el estado en el que se acaba es el estado de error I No es posible determinar mediante un ordenador (en tiempo finito) si una instrucción cualquiera, en un estado cualquiera, acabará de ejcutarse en un tiempo finito o no. S = { (”x”, f loat, 1.2) } no pertenece realmente al dominio de la aplicación f asociada a O, dado que no existe en el ninguna variable de nombre ”peso”. En estos casos, la ejecución de la orden lleva el programa a un estado especial de error: f (S) = error Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 7/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 8/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Semántica denotacional de las órdenes Semántica denotacional de las órdenes Detección de errores La función semántica Sem I En general, si el procesador de un lenguaje (traductor, compilador, intérprete o intérprete de código intermedio) puede determinar que una instrucción va a fallar en algunos o todos los estados de ejecución en los que se va a ejecutar, entonces: I Se debe informar de ello, y hacerlo tan pronto como sea posible, ya que eso beneficia la fiabilidad del programa (se evitan errores no descubiertos que provocan resultados erróneos y alargan los tiempos de desarrollo). I I La función Sem (por función semántica) asigna a cada orden posible su correspondiente función de transición. Consideramos esta función como el significado (semántica) de la orden. I En el ejemplo visto antes ( O = peso = peso + 1 ) f = Sem[O] = Sem[peso = peso + 1] Es un principio importante y que se deberı́a seguir por los lenguajes de programación Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 9/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 10/91. Cap. 5. Órdenes. Semántica denotacional de las órdenes Semántica denotacional de las órdenes Órdenes equivalentes Dos ordenes O1 y O2 se consideran equivalentes (se escribe O1 ≡ O2 ) cuando su semántica es la misma: O1 ≡ O2 ⇐⇒ Sem[O1 ] = Sem[O2 ] Un ejemplo de dos instrucciones equivalentes es: I O1 = y = x ; y = y + 1 I O2 = x = x + 1 ; y = x ; x = x − 1 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 11/91. Órdenes no deterministas I Existen órdenes que en algunos casos al ejecutarse pueden producir un estado de salida cualquiera de entre varios de un determinado conjunto de estados I En cada ejecución, el estado obtenido puede ser distinto, pero siempre pertenece al conjunto de estados de salida, que está bien definido, y que en general depende del estado de entrada. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 12/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Semántica denotacional de las órdenes Órdenes elementales Órdenes deterministas y no deterministas En general, podemos ver la función de transición como una aplicación de estados en conjuntos de estados: I I Una orden es determinista cuando, para cada estado de entrada, el conjuntos de estados de salida posibles tiene un único elemento. Una orden es no determinista cuando existe al menos un estado de entrada para el cual la orden conduce a un conjunto de estados de salida con más de un elemento. Indice de la sección Sección 2 Órdenes elementales 2.1. La órden skip 2.2. Asignaciones 2.3. Llamadas a procedimiento Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 14/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 13/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes elementales Órdenes elementales La órden skip La órden skip Órdenes elementales Existen varias clases de órdenes, y formas de combinarlas entre si para obtener nuevas órdenes. Distinguimos dos categorı́as: I Órdenes elementales: no están obtenidas combinando otras órdenes I Órdenes compuestas: se obtienen combinando entre sı́ otras órdenes, elementales o compuestas. I La orden skip es la más sencilla posible. I No comporta ninguna variación del estado de ejecución (no hace nada) I La función de transición asociada es la función identidad (aplica cada estado en si mismo). en esta sección comenzaremos viendo las primeras de ellas Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 15/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 16/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes elementales Órdenes elementales Asignaciones Asignaciones La órden de asignación Estructura de una órden de asignación I Una asignación es una orden que indica explı́citamente el nuevo valor de una variable en el estado de ejecución de destino En todos los lenguajes de programación la asignación tiene esta sintaxis: exprizq opasig exprder I La asignación es la más importante de las órdenes elementales, y constituye la base de todo el resto de órdenes. donde: I La asignación incluye información sobre la variable a modificar y el nuevo valor que se le debe asignar I exprizq es una expresión, en concreto un acceso a una variable de tipo T (al evaluarse, produce como resultado una referencia a una variable de tipo T ). I exprder es una expresión de tipo T I opasig es el token de asignación, normalmente = o := Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 18/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 17/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes elementales Órdenes elementales Asignaciones Asignaciones Ejecución de la orden de asignación Para ejecutar la asignación en un estado S, es necesario: 1 2 3 Evaluar exprizq , interpretando la expresión como de tipo ref(T ), y obteniendo una referencia a una variable v = eval(exprizq , S) ∈ ref(T ) Evaluar exprder , interpretando la expresión como de tipo T , y obteniendo un valor x = eval(exprder , S) ∈ T Almacenar en la zona de memoria asociada a la variable v el nuevo valor x Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 19/91. Fallos en la ejecución de la asignación La ejecución de la asignación falla si se cumple alguna de estas circunstancias: I No existe ningún tipo T tal que exprizq se puede interpretar como de tipo ref(T ) y exprder se pueda interpretar como de tipo T I Falla la evaluación de exprder I Falla la evaluación de exprizq I La evaluación de exprizq produce N U LL Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 20/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes elementales Órdenes elementales Asignaciones Asignaciones Asignaciones múltiples Asignaciones múltiples en Python En algunos lenguajes se contemplan las asignaciones múltiples: expr − izq1 , expr − izq2 · · · expr − izqn Este lenguaje contempla asignaciones múltiples, por ejemplo: 1 x , y = 1 ,2 opasig expr − der1 , expr − der2 · · · expr − dern es semejante a multiples sentencias de asignación, excepto en que el orden en el que se efectuan puede ser releveante si hay alguna variable referenciada tanto a la izquierda como la derecha (a no ser que se usen variables temporales intermedias) asigna el valor 1 a x y el valor 2 a y. Si hay coincidencias a la izquierda y la derecha, se usan variables intermedias, por ejemplo: 1 x,y = y,x Cap. 5. Órdenes. Órdenes elementales Llamadas a procedimiento Llamadas a procedimiento Llamadas a procedimiento Una llamada a procedimiento es una orden en la cual se incluye: I Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 22/91. Cap. 5. Órdenes. Órdenes elementales I intercambia los valores de x e y. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 21/91. El nombre de un procedimiento (subprograma que no devuelve un valor). Una lista de expresiones (posiblemente vacı́a) que se denominan los parámetros actuales de la llamada Ejecución de llamadas a procedimiento La ejecución de una llamada a procedimiento conlleva: I La evaluación de los parámetros actuales I Las inicialización de los parámetros formales con los valores obtenidos al evaluar los parámetros actuales I La ejecución de las órdenes que forman el cuerpo del procedimiento La ejecución falla si falla alguna de las evaluaciones o ejecuciones citadas en la lista anterior. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 23/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 24/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes elementales Órdenes compuestas Llamadas a procedimiento Llamadas a procedimiento I En lo que se refiere a la sintaxis, las llamadas a procedimiento son órdenes elementales. I Desde el punto de vista semántico, estas órdenes son compuestas, pues la función de transición asociada se obtiene por composición otras funciones de transición. I Los procedimientos se estudian con más detalle más adelante en el temario. Indice de la sección Sección 3 Órdenes compuestas 3.1. 3.2. 3.3. 3.4. 3.5. Composición Secuencial Composición colateral Órdenes bloque Órdenes condicionales Ordenes iterativas Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 26/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 25/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Clasificación de las órdenes compuestas Órdenes compuestas I I Una orden compuesta se construye combinando varias órdenes válidas, de acuerdo con determinadas reglas sintácticas propias de cada lenguaje. La semántica de una orden compuesta es una aplicación que depende las aplicaciones asociadas a las otras órdenes que forman la primera. Veremos los siguientes tipos de órdenes compuestas: I Composición de órdenes I I I I Órdenes condicionales Órdenes iterativas: I I I Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 27/91. Secuencial Colateral (concurrente) Bucles indefinidos Bucles definidos Bloques Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 28/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición Secuencial Composición Secuencial Composición secuencial: notación Sean O1 y O2 dos órdenes cualquiera, podemos escribir una nueva orden O como sigue: O = O1 ; O2 Decimos que O es la composición secuencial de O1 y O2 Composición secuencial: ejecución La ejecución O1 ; O2 se lleva a cabo en dos pasos: 1 Se ejecuta O1 , si esta ejecución falla, también falla la de O1 ; O2 2 Se ejecuta O2 , si esta ejecución falla, también falla la de O1 ; O2 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 29/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 30/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición Secuencial Composición Secuencial Semántica de la composición secuencial En cuanto a la semántica de O1 ; O2 se cumple que: Sem[O1 ; O2 ] = Sem[O1 ] ◦ Sem[O2 ] Aquı́, el sı́mbolo ◦ denota la composición de aplicaciones, es decir, para dos aplicaciones f y g, tales que el rango de f es el dominio de g, y tal que x es un elemento del dominio de f , se cumple que: (f ◦ g)(x) = g(f (x)) Ejemplo de composición secuencial Sean: I O1 = x = x + 1 I O2 = x = x + 2 I O = O1 ; O2 = x = x + 1 ; x = x + 2 Entonces: Sem[O] = Sem[x = x + 1 ; x = x + 2] = Sem[x = x + 1] ◦ Sem[x = x + 2] = Sem[x = x + 3] Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 31/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 32/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición Secuencial Composición Secuencial Asociatividad de la composición secuencial La composición de aplicaciones es asociativa, y por tanto también lo es la composición secuencial de órdenes: (O1 ; O2 ) ; O3 ≡ O1 ; (O2 ; O3 ) Esta orden se puede escribir simplemente como Composición secuencial en los LLPP En la mayorı́a de los lenguajes, el sı́mbolo ; denota composición secuencial, si bien suele ser necesario añadirlo también después de la última orden de una secuencia de ellas (excepto en Pascal), es decir, la orden: O1 ; O2 ; · · · ; On Se escribe como sigue: O1 ; O2 ; O3 O1 ; O2 ; · · · ; On ; Lógicamente, la notación que se puede extender a secuencias: O1 ; O2 ; · · · ; On Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 33/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 34/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición colateral Composición colateral Composición colateral: notación Sean O1 y O2 dos órdenes cualquiera, podemos escribir una nueva orden O como sigue: O = O1 , O2 Ejecución de la composición colateral I La ejecución de O1 , O2 conlleva la ejecución (posiblemente simultánea) de O1 y O2 I Aquı́, ”posiblemente simultánea” significa que no se requiere que la ejecución de una de ellas comience después de que finalice la otra. I En el momento que comienza la ejecución de la orden O1 , O2 puede comenzar también la ejecución de O1 y/o la ejecución de O2 I La ejecución de O1 , O2 finaliza tan pronto como hayan finalizado tanto la ejecución de O1 cómo la de O2 (una de ellas podrı́a acabar antes que la otra) Decimos que O es la composición secuencial de O1 y O2 La ejecución de la sentencia O conlleva la ejecución de O1 y O2 al mismo tiempo Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 35/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 36/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición colateral Composición colateral Lecturas simultáneas, escrituras excluyentes I Todos los cálculos asociados a la evaluación de las expresiones o accesos a memoria de una orden pueden ocurrir simultáneamente con los de la otra, incluyendo lecturas del valor de una misma variable. I La excepción es la escritura de un valor de una variable en una orden: no se puede solapar con ningún acceso de lectura o escritura a esa misma variable de otras órdenes. Orden relativo indeterminado I El orden relativo de ejecución de cada uno de los pasos de cada instrucción es, en general, arbitrario e impredecible, probablemente distinto en cada ejecución. I Por tanto, la orden O1 , O2 puede no ser determinista, ya que el estado de salida puede depender de dicho orden relativo de ejecución de cada uno de los pasos elementales. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 37/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 38/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición colateral Composición colateral Propiedades de la composición colateral La composición colateral es conmutativa y asociativa, es decir: Ejemplo de composición colateral determinista Una orden, a pesar de ser una composición colateral, puede ser determinista, por ejemplo, la siguiente: O1 , O2 ≡ O2 , O1 (O1 , O2 ) , O3 ≡ O1 , (O2 , O3 ) Por tanto, tiene sentido escribir la instrucción: O1 , O2 , . . . , On x=2+z , y=1 El estado de salida es único a partir de cualquier estado de entrada, independientemente de cómo se ordenen los cálculos en el tiempo como consecuencia el orden en el que se escriben las sentencias es irrelevante de cara a la ejecución Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 39/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 40/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición colateral Composición colateral Ejemplo de composición colateral no determinista Por supuesto, algunas composiciones colaterales son no deterministas, por ejemplo, supongamos un estado de ejecución S donde existe una variable x con valor 0, y otra variable y. Se ejecuta la orden: x=1 , y=x+x A la salida, x siempre vale 1, pero respecto a y hay tres posibilidades (ver siguiente transparencia) Posibles estados de salida del ejemplo I Si la evaluación de la expresión x + x acaba completamente antes de que se ejecute la asignación x = 1, entonces a la salida y vale 0 I Si la asignación x = 1 acaba antes de que comience la evaluación de x + x, entonces a la salida y vale 2 I Si la asignación x = 1 tiene lugar entre las dos evaluaciones de la expresión x, entonces a la salida y vale 1 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 41/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 42/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Composición colateral Órdenes bloque Concurrencia en varios lenguajes Los lenguajes C/C++, Ada, Java y C# no hay un mecanismo explı́cito para composición colateral de órdenes, tal y como se ha visto aquı́ Existen, sin embargo, construcciones para ejecutar simultáneamente varias partes de un programa (concurrencia), que permiten disintos niveles de concurrencia Órdenes bloque I I Estas órdenes son simplemente el agrupamiento por composición secuencial de varias órdenes formando una única orden compuesta. Para mejorar la legibilidad y simplificar el análisis sintáctico, es necesario usar dos tokens de inicio y fin de bloque. I I I En algunas implementaciones de C/C++ existe el subprograma fork para crear un proceso hijo del actual, aunque no se comparten las variables. I En Ada pueden existir tareas (tasks) concurrentes. I En Java y C# pueden existir varias hebras (threads) ejecutandose simultáneamente. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 43/91. I en los lenguajes derivados de Algol (Pascal,Ada, Modula), se usa begin /end , en los lenguajes más modernos derivados de C/C++ (Java,C#), se usan la llaves: { } En python, la agrupación en bloques se hace usando la indentación de las lineas en el archivo ascii donde aparecen. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 44/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes bloque Órdenes bloque Órdenes bloque con declaraciones locales Órdenes bloque con declaraciones locales en C En algunos lenguajes se permite declaraciones de variables locales a las órdenes bloque: Las declaraciones van dentro del bloque, al principio: 1 I I [ declaracion1 ; declaracion2 ; ··· declaracionn ; ] 2 En C y Ada, al principio del bloque 3 En C++, Java y C#, en cualquier parte del bloque (mezcladas con las órdenes) { 4 5 6 [ orden1 ; orden2 ; ··· ordenn ; ] 7 8 9 10 11 } Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 45/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 46/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes bloque Órdenes bloque Órdenes bloque con declaraciones locales en C++,Java,C# Las declaraciones pueden ir mezcladas con la sentencias 1 2 3 4 4 [ declaracion2 ; ] [ orden2 ; ] 5 6 5 6 7 7 ··· 8 8 9 9 [ declaracionn ; ] [ ordenn ; ] 10 11 12 Se entepone la palabra clave declare, 1 [ declaracion1 ; ] [ orden1 ; ] 3 Órdenes bloque con declaraciones locales en Ada { 2 } 10 11 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 47/91. 12 declare [ declaracion1 ; ] [ declaracion2 ; ] ··· [ declaracionn ; ] in begin [ orden1 ; ] [ orden2 ; ] ··· [ ordenn ; ] end Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 48/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes condicionales Órdenes condicionales Órdenes condicionales: notación Sean O1 y O2 os órdenes cualquiera, y e una expresión de tipo lógico. Podemos entonces construir la orden O siguiente: Semántica de la orden condicional Sea S un estado de ejecución cualquiera, entonces: Sem[ if e then O1 else O2 ](S) = O = if e then O1 else O2 Esta orden se denomina orden condicional u orden if. Su ejecución comporta la ejecución de O1 u O2 (nunca ambas) en función del resultado de evaluar la expresión e = Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 49/91. Cap. 5. Órdenes. Sem[O1 ](S) si eval(e, S) = true Sem[O2 ](S) si eval(e, S) = f alse Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 50/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes condicionales Órdenes condicionales Opcionalidad del else La parte else puede no aparecer, en este caso La orden elseif Algunos lenguajes contemplan la construcción elseif : if c then O ≡ if c then O else skip Un else siempre se refiere al último if : if e1 then if e2 then O2 else O3 = if e1 then (if e2 then O2 else O3 ) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 51/91. if c1 then O1 else if c2 then O2 else if . . . . . . else if cn then On [else On+1 ] ≡ if c1 then O1 elseif c2 then O2 elseif . . . . . . elseif cn then On [else On+1 ] Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 52/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes condicionales Órdenes condicionales Órden if en varios lenguajes En C/C++, Java y C# están disponibles estas formas: 1 2 3 4 Órden if en Ada if ( e ) orden1 ; // o r d e n s i m p l e [ else orden2 ; ] // o r d e n s i m p l e 7 8 9 1 2 3 4 5 6 En Ada tienen estas forma: 5 if ( e ) { orden1,1 ; · · · ; orden1,n1 } [ else { orden2,1 ; · · · ; orden2,n2 ; } ] i f expr then orden1,1 ; · · · ; orden1,n1 ; [ else orden2,1 ; · · · ; orden2,n2 ; ] end i f ; Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 54/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes condicionales Órdenes condicionales elsif en Ada Órden if en Python Ada incorpora una forma abreviada para el else if, mediante la palabra clave elsif 2 3 4 5 6 7 8 9 10 i f expr0 then orden0,1 ; e l s i f expr1 orden1,1 ; ··· e l s i f exprk ordenk,1 ; [ e l s e exprk+1 ordenk+1,1 end i f ; Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 53/91. 1 En Python la forma es: 1 2 · · · ; orden0,n0 3 4 · · · ; orden1,n1 5 6 7 · · · ; ordenk,nk 8 ; · · · ; ordenk+1,nk+1 ] Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 55/91. if e: orden1,1 ··· orden1,n1 [ else : orden2,1 ··· orden2,n2 ] El if (o else) abarca todas las sentencias cuya indentación es superior a la del if (o else), y que siguen al if (o else) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 56/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Órdenes condicionales Órdenes condicionales La orden switch Órden switch en C/CC++ y Java La orden case o switch es una variante del if if e = e1 then O1 elseif e = e2 then O2 elseif Estos lenguajes tienen una sintaxis similar para el switch 1 ... 2 . . . elseif e = en then On [else On+1 ] 3 ≡ 4 case e is e1 then O1 ; e2 then O2 ; . . . 5 . . . ; en then On [else On+1 ] 6 7 de esta forma se evitan las múltiples apariciones de e, y se mejora la legibilidad. 8 9 10 11 12 Cap. 5. Órdenes. C# usa la sintaxis de C/C++, pero sin la posibilidad (ni necesidad) de incluir los breaks 4 5 6 7 8 9 10 11 12 · · · ; ordenk,nk ; [ break ; ] ] ; · · · ; ordenk+1,nk+1 ; [ break ; ] ] ] Órdenes condicionales Órden switch en C# 3 · · · ; orden2,n2 ; [ break ; ] ] Órdenes compuestas Órdenes condicionales 2 · · · ; orden1,n1 ; [ break ; ] ] Cap. 5. Órdenes. Órdenes compuestas s w i t c h ( expr0 { case expr1 : [ orden1,1 ; case expr2 : [ orden2,1 ; ··· case exprk : [ ordenk,1 ; [ default : [ ordenk+1,1 } ) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 58/91. las expresiones son de tipos simples (enteros,caracteres, enumerados, lógicos), y en Java tambien de sus respectivas wraper classes Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 57/91. 1 s w i t c h ( expr0 { case expr1 : [ orden1,1 ; case expr2 : [ orden2,1 ; ··· case exprk : [ ordenk,1 ; [ default : [ ordenk+1,1 } Órden case en Ada Ada incorpora la orden case (equivalente a switch), (el lenguaje obliga a cubrir todos los casos posibles) ) 1 2 3 · · · ; orden1,n1 ; ] 4 5 · · · ; orden2,n2 ; ] 6 7 8 · · · ; ordenk,nk ; ] 9 10 ; · · · ; ordenk+1,nk+1 ; ] ] Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 59/91. las expresiones son literales de tipos primitivos. 11 case expresion i s when expr1 => orden1,1 ; · · · when expr2 => orden2,1 ; · · · ··· when exprk => ordenk,1 ; · · · [ when o t h e r s => ordenk+1,1 ; · · · ; end case ; orden1,n1 ; ; orden2,n2 ; ; ordenk,nk ; ordenk+1,nk+1 ; ] Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 60/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Ordenes iterativas Bucles definidos e indefinidos I Las órdenes iterativas (o bucles) son órdenes cuya ejecución supone la ejecución repetida de una misma orden O un número de veces: I Si el numero de veces se puede calcular (durante la ejecución) antes de ejecutar el bucle, se llama bucle definido. Estas órdenes siempre acaban, si acaba cada iteración. I Cada ejecución de la sentencia O se denomina iteración del bucle. I Si el número de veces no se puede calcular sin ejecutar el bucle, se llama bucle indefinido. Estas órdenes pueden no acabar, aún cuando acabe cada iteración. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 61/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 62/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles indefinidos Semántica del bucle while El bucle indefinido más común en los lenguajes de programación es el bucle while. Si e es una expresión lógica y O una orden cualquiera, podemos construir una nueva orden: while c do O Ejecutar esta orden supone evaluar c, y si es false, terminar, en caso contrario, ejecutar O y volver a empezar. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 63/91. Sean: I S un estado de ejecución cualquiera, I O una orden cualquiera I f la función de transición de O, es decir f = Sem[O] I c una expresión lógica I A = {m ∈ N t.q. eval(c, f m (S)) = f alse} (el conjunto de los naturales m tales que justo tras ejecutar m veces la orden O, la expresión c se evalua a false) I n = el mı́nimo del conjunto A (supuesto que A 6= ∅) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 64/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Semántica del bucle while Definición recurrente de la semántica del while Si, en el estado S cada iteración termina (es decir, si A se puede ejecutar al menos n veces, y cada vez A termina), entonces: I Alternativamente, la función Sem[while c do O] se puede definir como la única función de transición tal que se hace cierta la siguiente equivalencia (recurrente) Si A es no vacı́o entonces el bucle termina, y: while c do O Sem[while c do O](S) = f n (S) I ≡ if c then ( O ; while c do O ) Si A es vacı́o el bucle no termina, y: Sem[while c do O](S) = error Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 65/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 66/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Los bucles do-while y repeat-until Bucles indefinidos en C/C++ Son bucles basados en el bucle while En C/C++, Java y C# están disponibles estas formas de bucles indefinidos: do O while c ≡ O ; while c do O repeat O until c ≡ do O while not c 1 2 while ( e ) O ; // o r d e n s i m p l e 3 4 5 while ( e ) { O1 ; · · · ; On ; } 6 7 8 9 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 67/91. do O1 ; · · · ; On while ( e ) ; Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 68/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles indefinidos en Ada En Ada tienen estas forma: 1 2 3 [ w h i l e e ] loop O1 ; · · · ; On ; end loop ; el while e puede omitirse, y en este caso es un bucle infinito, a no ser que se interrumpa (ver más adelante la orden exit de Ada) Bucles indefinidos en Python En Python la forma es: 1 2 3 4 while e : O1 ··· On El bucle abarca todas las sentencias cuya indentación es superior a la del while Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 69/91. Cap. 5. Órdenes. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 70/91. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas La sentencia break La sentencia break Es una sentencia que puede aparecer en un bucle, y que al ejecutarse finaliza dicho bucle. Es útil cuando aparece en un if while c do Si aparece directamente no es muy útil: while c do ( O1 ; break ; O2 ) ( O1 ; if e then break ; O2 ) ≡ b = true ; ≡ if c then O1 while b and c do ( O1 ; b = not e ; if b then O2 ) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 71/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 72/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas La sentencia continue La sentencia continue Es una sentencia que puede aparecer en un bucle, y que hace que se vuelva a la evaluación de la condición. Si aparece directamente no es muy útil: Es útil cuando aparece en un if while c do ( O1 ; if e then continue ; O2 ) while c do ≡ ( O1 ; continue ; O2 ) while c do ≡ ( O1 ; if not e then O2 ) while c do O1 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 73/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Break y continue en varios lenguajes I Están disponibles en la mayorı́a de los lenguajes I En C/C++, Java, C# y Python se llaman break y continue I En Ada la orden break se llama exit, y admite además una forma condicional (exit when e), con una expresión lógica (e). I Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 74/91. Bucles definidos I Los bucles definidos sirven para ejecutar una sentencia un número finito de veces (este número es computable durante la ejecución justo antes de ejecutar el bucle) I Al ejecutarse un bucle definido, una variable (no modificable) toma cada uno de los valores contenidos en una colección (un rango de valores de un tipo simple, un array, una lista, un diccionario, u otros tipos de datos). Tras tomar cada valor, se ejecuta la sentencia. I Un rango de enteros se puede ver como un caso particular de una colección Además, en Ada se pueden etiquetar las sentencias con identificador, y usarlo para terminar un bucle distinto del mas interno que contiene el break (con exit ident [when e]) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 75/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 76/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles definidos Bucles definidos: semántica Una sintaxis genérica para el bucle es: Supongamos que, en un estado S, se cumple: eval(e, S) = { a1 , a2 , . . . , an } foreach ident in e do O donde: entonces, en dicho estado S se da la siguiente equivalencia: I O es una sentencia cualquiera I e es una expresión que, al evaluarse en un estado S, si no falla la evaluación, produce una colección (homogénea) de valores {v1 , v2 , . . . , vn }, todos ellos de tipo T I foreach ident in e do O ≡ ident = a0 ; O ; ident = a1 ; O ; ident es un identificador que se usará para declarar (implicitamente) una variable local nueva de tipo T cuyo ámbito es O (la variable no deberı́a ser modificable) ··· ident = an ; O ; Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 78/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 77/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles definidos: semántica I Si la evaluación de e produce una colección vacı́a, no se ejecuta O ninguna vez. I Algunos tipos de colecciones tienen asociado un orden para los elementos (por ejemplo rangos o arrays), en otras el orden está indeterminado. Bucles for en C/C++ Estos lenguajes no contemplan los bucles definidos. El bucle for es un bucle indefinido que suele usarse para iterar sobre colecciones de objetos. Su forma es: 1 f o r ( ordenini ; expr ; ordensig ) orden ; donde: I I I I Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 79/91. ordenini es una sentencia, usualmente de incialización ordensig es una sentencia, usualmente avanza al siguiente elemento de la serie expr es una sentencia, normalmente una expresión de tipo lógico o entero orden es una sentencia arbitraria (simple o una sentencia bloque) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 80/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles for en C/C++ : semántica La sentencia for que hemos visto es completamente equivalente a este bucle while: 1 Bucles for con declaración en C++ ordenini ; 4 5 6 7 1 2 3 En C++ existe una forma de bucle for indefinido con una declaración de una variable local al bucle: 2 w h i l e ( expr ) { orden ; ordensig ; } f o r ( tipo ident = exprini ; exprparar ; ordensig ) orden ; Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 81/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 82/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles for con declaración en C++ El anterior bucle es equivalente al siguiente, que incluye explı́citamente la declaración de la variable local: I En Java y C#, están disponibles los bucles for como bucles indefinidos, con una sintaxis y semántica similar a la de C/C++ tipo ident = exprini ; I En Ada existen bucles for definidos sobre rangos de tipos primitivos (no flotantes) w h i l e ( exprparar ) { ordensig orden ; } I En Java (1.5), C# y Python existen bucles definidos sobre arrays, listas, y colecciones en general 1 Bucles for definidos en varios lenguajes { 2 3 4 5 6 7 8 9 } Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 83/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 84/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles for en Ada Semántica de los bucles for en Ada La forma de los bucles es esta: 1 2 3 f o r ident i n e1 . . e2 loop O1 ; O2 ; · · · ; On end loop ; El bucle for de Ada es equivalente al siguiente bucle while 1 2 3 4 5 Aquı́: 6 I I e1 y e2 son dos expresiones del mismo tipo (entero, carácter, enumerado o lógico). Al evaluarse, producen un rango concreto de valores. 7 8 9 ident es el nombre de la variable de control (es una variable local al cuerpo del bucle, de solo lectura, y del mismo tipo que e1 y e2 , declarada implicitamente). declare ident : T := e1 ; ultimo : T := e2 ; i n begin w h i l e ident <= ultimo loop O1 ; O2 ; · · · ; On ident = T ’ V a l ( T ’ Pos ( ident)+1) ; end loop ; end ; Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 86/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles for en Java y C# El bucle for básico de Java y C# es semejante (sintáctica y semánticamente) al de C++ 2 aquı́, T es el nombre del tipo (discreto) de e1 y e2 Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 85/91. 1 f o r ( [ tipo ] ident = exprini ; exprparar ; ordensig ) orden ; Este bucle puede incluir opcionalmente una declaración de variable local. Bucles for sobre colecciones en Java En Java los bucles for pueden servir para iterar sobre: I arrays I instancias de clases que implementan el interfaz Collection la sintaxis es: 1 2 f o r ( tipo identif icador : expr ) sentencias aquı́, expr es una expresión de tipo array o colección Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 87/91. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 88/91. Cap. 5. Órdenes. Cap. 5. Órdenes. Órdenes compuestas Órdenes compuestas Ordenes iterativas Ordenes iterativas Bucles for sobre colecciones en Java Bucles for sobre colecciones en Python En C#, el bucle foreach puede iterar tambien sobre: I I arrays 2 3 la sintaxis es: 2 1 instancias de clases que implementan el interfaz IEnumerable 1 En python, un bucle for puede iterar sobre cualquier tipo de colección: listas, tuplas, conjuntos, diccionarios, etc.. . f o r e a c h ( tipo identif icador i n expr ) sentencias aquı́, expr es una expresión de tipo array o colección, y el identificador se declara implicitamente como una variable local del tipo de los elementos de la colección o array. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 89/91. Cap. 5. Órdenes. Órdenes compuestas Ordenes iterativas fin del capı́tulo. Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 91/91. 4 5 f o r ident i n expr : sentencia1 sentencia2 ··· sentencian en este lenguaje, la iteración sobre rangos de valores de tipos primitivos es un caso particular de la iteración sobre colecciones (se usa la función range) Autor: Carlos Ureña. Fecha creación: December 3, 2009. Página: 90/91.