1 / 35

Paso de parámetros y arreglos

Paso de parámetros y arreglos. Gracias a los interpretes hemos explorado varias características que ofrecen los lenguajes de programación dentro de las cuales encontramos:. Las aplicaciones (llamadas a procedimiento) Resolución de nombres (gracias al establecimiento de un ambiente)

dayton
Download Presentation

Paso de parámetros y arreglos

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Paso de parámetros y arreglos

  2. Gracias a los interpretes hemos explorado varias características que ofrecen los lenguajes de programación dentro de las cuales encontramos: • Las aplicaciones (llamadas a procedimiento) • Resolución de nombres (gracias al establecimiento de un ambiente) • Condicionamiento de la ejecución. • Creación de variables locales. • Creación de procedimientos por parte del usuario, • Asignación de variables • Recursión • Alcance dinámico y asignación o afectacion dinámica

  3. Otras características de los LP • Modificando nuestro interprete podremos: • Seguir explorando las características de los LP’s • Expresar alternativas semánticas para los LP de una manera clara y precisa de forma a enfantizar sus diferencias esenciales.

  4. Otras características de los LP • Extensiones a nuetro interprete para estas sesiones: • Manejo de arreglos. • Paso de parámetros. • Llamadas por Valor. • Llamadas por referencia. • Llamadas por el valor del resultado. • Llamadas por resultado. • Llamadas por nombre (o por retraso). • Llamadas por necesidad. • Parámetros opcionales • Parámetros por nombre (vs. posición)

  5. Añadiendo arreglos • Muchos lenguajes de programación incluyen estructuras de datos compuestos de multiples elementos conocidos como agregados. • En Scheme encontramos los siguientes agregados: • Pares. • Vectores. • Cadenas de caracteres. • Existen dos representaciones para los agregados: • Directa (ej. arreglos en pascal). El paso de un parámetro de este tipo a un procedimiento se hace por valor i.e. se hace una copia del agregado. • Indirecta (ej. C). El paso de un parámetro de este tipo a un procedimiento se hace por referencia i.e. se envía un apuntador al agregado que se quiere enviar como parámetro.

  6. Añadiendo arreglos Agreguemos a nuestro interprete las siguientes extensiones para el manejo de arreglos: • Una nueva forma que permita la creación de arreglos y su asociación a una varable. • Una expresión que permita la asociación local de una variable con un arreglo. • Una expresión que permita acceder a un elemento de un arreglo. • Una expresión que permita la asignación de valores a un elemento de un arreglo.

  7. Sintaxis abstracta y concreta para la adición de arreglos al interprete <form> ::= definearray <var><exp> definearray (var len-exp) <exp> ::= letarray <arraydecls> in <exp> letarray (arraydecls body) | <array-exp>[<exp>] arrayref (array index) | <array-exp>[<exp>] := arrayassign (array index <exp> exp) <array-exp> ::= <varref> | (<exp>) <arraydecls> ::= <arraydecl> {;<arraydecl)}* decl (var exp) Un arreglo es una secuencia de celdas las cuales contienen valores expresados (representación indirecta): Arreglo = {Celda(Valor expresado)} Valor expresado = Número + Procedimiento + Arreglo Valor denotado = Celda (Valor expresado)

  8. ADT para el arreglo (define make-array (lambda (length) (let ((array (make-vector (+ length 1)))) (vector-set! array 0 '*array*) array))) (define array? (lambda (x) (and (vector? x) (eq? (vector-ref x 0) '*array*)))) (define array-ref (lambda (array index) (vector-ref array (+ index 1)))) (define array-set! (lambda (array index value) (vector-set! array (+ index 1) value)))

  9. ADT para el arreglo… (define array-whole-set! (lambda (dest-array source-array) (let ((source-len (vector-length source-array))) (letrec ((loop (lambda (n) (if (< n source-len) (begin (vector-set! dest-array n (vector-ref source-array n)) (loop (+ n 1))))))) (loop 1))))) (define array-copy (lambda (array) (let ((new-array (make-array (- (vector-length array) 1)))) (array-whole-set! new-array array) new-array)))

  10. (define eval-exp (lambda (exp env) (variant-case exp (varref (var) (denoted->expressed (apply-env env var))) (app (rator rands) (apply-proc (eval-rator rator env) (eval-rands rands env))) (varassign (var exp) (denoted-value-assign! (apply-env env var) (eval-exp exp env))) (letarray (arraydecls body) (eval-exp body (extend-env (map decl->var arraydecls) (map (lambda (decl) (do-letarray (eval-exp (decl->exp decl) env))) arraydecls) env))) (arrayref (array index) (array-ref (eval-array-exp array env) (eval-exp index env))) (arrayassign (array index exp) Modifs al interprete para manejo de arreglos (arrayassign (array index exp) (array-set! (eval-array-exp array env) (eval-exp index env) (eval-exp exp env))) (else ...))))

  11. Modifs al interprete para manejo de arreglos (define eval-rator (lambda (rator env) (eval-exp rator env))) (define eval-rands (lambda (rands env) (map (lambda (rand) (eval-rand rand env)) rands))) (define eval-rand (lambda (exp env) (expressed->denoted (eval-exp exp env)))) (define apply-proc (lambda (proc args) (variant-case proc (prim-proc (prim-op) (apply-prim-op prim-op (map denoted->expressed args))) (closure (formals body env) (eval-exp body (extend-env formals args env))) (else (error "Invalid procedure:" proc)))))

  12. Paso por valor de arreglos (representación indirecta ) (define denoted->expressed cell-ref) (define denoted-value-assign! cell-set!) (define do-letarray (compose make-cell make-array)) (define eval-array-exp eval-exp) (define expressed->denoted make-cell)

  13. Representación de celdas (define cell-ref (lambda (x) (if (cell? x) (vector-ref x 1) (error "Invalid argument to cell-ref:" x)))) (define cell-set! (lambda (x value) (if (cell? x) (vector-set! x 1 value) (error "Invalid argument to cell-set!:" x)))) (define cell-swap! (lambda (cell-1 cell-2) (let ((temp (cell-ref cell-1))) (cell-set! cell-1 (cell-ref cell-2)) (cell-set! cell-2 temp)))) (define cell-tag "cell") (define make-cell (lambda (x) (vector cell-tag x))) (define cell? (lambda (x) (and (vector? x) (= (vector-length x) 2) (eq? (vector-ref x 0) cell-tag))))

  14. Arreglos representación directa Arreglo = {Celda(Número + Procedimiento)} Valor expresado = Número + Procedimiento + Arreglo Valor denotado = Celda (Número)+Celda (Procedimiento)+Arreglo En la reprresentación directa cuando un arreglo es pasado por valor, el parámetro formal es afectado a una copia de la secuencia de valores. En caso de que exista una asignación dentro del procedimeinto, solo la copia local del arreglo se verá afectada.

  15. Paso por valor de arreglos (representación directa ) Habrá que modificar el procedimiento array-set! de manera a que no pueda existir un arreglo dentro de otro: (define array-set! (lambda (array index value) (if (array? value) (error "Cannot assign array to array element" value) (vector-set! array (+ index 1) value))))

  16. Paso por valor de arreglos (representación directa )… (define eval-array-exp eval-exp) (define expressed->denoted (lambda (exp-val) (if (array? exp-val) (array-copy exp-val) (make-cell exp-val)))) (define denoted->expressed (lambda (den-val) (if (array? den-val) den-val (cell-ref den-val)))) (define denoted-value-assign! (lambda (den-val exp-val) (cond ((not (array? den-val)) (cell-set! den-val exp-val)) ((array? exp-val) (array-whole-set! den-val exp-val)) (else (error "Must assign array:" den-val))))) (define do-letarray make-array)

  17. 3 8 3 8 3 8 3 9 5 7 4 5 6 4 5 6 4 3 9 4 5 6 4 5 6 4 Representación indirecta Vs. directa letarray u[3]; v[2] in begin u[0] := 5; u[1] := 6; u[2] := 4; v[0] := 3; v[1] := 8; let p = proc (x) begin x[1] : =7; x := v; x[1] := 9 end in p(u) end x u v x u v (a) x u x u v v (b)

  18. Llamada por referencia • En Scheme todo tipo de dato se pasa por valor. • Usa la representación directa para los escalares tal que los valores numéricos. • Para los agregados usa una representación indirecta por razones de eficiencia. • En algunas ocasiones es necesario o conveniente el poder asignar o afectar los valores asociados a los parámetros con el fin de comunicarle un resultado al procedimiento llamante. Esto sería un efecto secundario que a veces es dificil de entender

  19. Los alias y el paso por referencia Algunos problemas provocados por el paso por referencia los evidencia el siguiente programa (suponga que los parámetros son pasados por referencia). • define swap = proc (x, y) begin x := +(x, y) y := -(x, y); x := -(x, y) end; define b =1; define c = 2; • swap(b, c); • b; 2 • c; 1 • swap(b,b) • b 0

  20. Modelando paso de parámetros por referencia… Para realizar el paso de parámetros por referencia (en cuanto a variables no del tipo de arreglos) solamente es necesario cambiar: (define eval-rand (lambda (rand env) (variant-case rand (varref (var) (apply-env env var)) (else (error "Invalid operand:" rand))))) <operand> :: = <exp> a <operand> ::= <varref>

  21. Modelando paso de parámetros por referencia… • En una implementación típica, el paso por referencia de un elemento de un arreglo se realiza a través de un apuntador. • En Scheme no es posible obtener un apuntador a un elemento de un arreglo (no existe un operador & como en C). • Es necesario crear un nuevo registro para lograrlo: • (define-record ae (array index)) • Nuestros operandos tendrian entonces la siguiente forma • <operand> ::= <varref> • | <arry-exp>[<exp>] • |<exp>

  22. Modelando paso de parámetros por referencia… Las siguientes modificaciones a nuetro interprete son necesarias: (define eval-rand (lambda (rand env) (variant-case rand (varref (var) (apply-env env var)) (arrayref (array index) (make-ae (eval-array-exp array env) (eval-exp index env))) (else (make-cell (eval-exp rand env)))))) (define denoted->expressed (lambda (den-val) (cond ((cell? den-val) (cell-ref den-val)) ((ae? den-val) (array-ref (ae->array den-val) (ae->index den-val))) (else (error "Can't dereference denoted value:" den-val)))))

  23. Modelando paso de parámetros por referencia… (define denoted-value-assign! (lambda (den-val val) (cond ((cell? den-val) (cell-set! den-val val)) ((ae? den-val) (array-set! (ae->array den-val) (ae->index den-val) val)) (else (error "Can't assign to denoted value:" den-val)))))

  24. 3 8 3 9 3 8 3 8 5 6 4 3 9 4 5 7 4 5 6 4 Modelando paso de parámetros por referencia… letarray u[3]; v[2] in begin u[0] := 5; u[1] := 6; u[2] := 4; v[0] := 3; v[1] := 8; let p = proc (x) begin x[1] : =7; x := v; x[1] := 9 end in p(u) end x, u v x, u v (a) u u v v x x (b)

  25. Llamadas por el valor del resultado y llamadas por resultado • Es de uso frecuente que el compilador aloje en localidades específicas (conocidas) de memoria, los parámetros pasados por valor de manera a que los procedimientos los accedan de forma directa. • En llamadas por referencia, esto no sucede así y las localidades específicas no se conocen sino hasta la propia invocación del procedimiento. • Las llamadas a procedimiento por referencia son menos eficientes. • Las llamadas por el valor del resultado combinan: • La eficiencia al acceder parámetros que se pasan por valor. • La habilidad de regresar información via los parámetros.

  26. Llamadas por el valor del resultado y llamadas por resultado • El parametro que es pasado por llamada por el valor del resultado es copiado a una localidad específica de la memoria al momento de la invocación del procedimiento. • El valor final del parámetro que es pasado por llamada por el valor del resultado es recopiado a su localidad original al finalizar el procedimeinto. • Las llamadas por el valor de resultado son más eficientes a expensas de un proceso menos eficiente de invocación y termino de procedimiento. • Depende de los accesos que el procedimeinto haga del parámetro en cuestión.

  27. Llamadas por el valor del resultado y llamadas por resultado • El paso por llamadas por el valor del resultado no sufre de los problemas de “alias”. • En la ausencia del problema de “alias” las llamadas por el valor del resultado tiene el mismo efecto que las llamadas por referencia. • Normalmente es el compilador quien hace la elección de que tipo de llamada utilizar. • Las llamadas por resultado tienen las mismas características que las llamadas por el valor del resultado excepto que solo se usan para transferir información del procedimiento llamante al llamado (ej. Un código de error) • Las llamadas por valor, las llamadas por el valor del resultado y las llamadas por resultado se conocen como llamadas por copia.

  28. Valores expresados o denotados ? Muchas de las diferencias en los lenguajes de programación estrivan en el manejo de: • Los valores expresados, los cuales son productos de la evaluación de una expresión. • Los valores denotados (aquellos valore que guardamos en memoria) normalmente más ricos que los expresados • Los valores “L-values” que aparecen del lado izquierdo en una asignación.

  29. Valores expresados o denotados ?... • En lenguajes imperativos tradicionales las expresiones ocurren en el lado derecho (R-values) de las asignaciones. • => El conjunto de valores expresados corresponde al conjunto • de valores almacenables en una localidad de memoria. • En algunos casos es necesario restringir los valores expresados de manera a evitar duplicaciones (ej. cunado se representan de manera directa los agregados) Ejemplo: Valor expresado = Numero Valor denotado = L-value + Arreglos + Procedimientos

  30. Valores expresados o denotados ?... • Estudiando los valores expresados y denotados de un lenguaje proporcionan un profundo conocimiento de la estructura del lenguaje de programación. • La estructura usada para el almacenamiento y manejo de los valores por un lenguaje de programación, determina en buena parte: • El poder de expresividad del lenguaje. • El nivel de eficiencia. • La estrategia de implementación.

  31. Llamadas por nombre y llamadas por necesidad. Algunas LP no evalúan los argumentos antes de pasarlas a un procedimiento, i.e.retrasan su evaluación: • No realizar evaluaciones innecesarias. • Evitar computaciones sin terminación (recuerde el ejemplo en conversion ).

  32. Llamadas por nombre y por necesidad. • Una de las formas para retrasar la evaluación del operando es pasar el arbol sintáctico (o codigo compilado) representando al operando. • De la misma manera que para la definición de los procedimientos habrá que crear una “closure” (su ambiente al momento de definirlo) para cada argumento. • Los “Closures” usados para retrasar la evaluación de los argumentos son conocidos como “thunks”. • El paso de parámetros en donde la evaluación de los argumentos es retrasado usando “thunk” se conoce como llamadas por nombre. • Almacenando la evaluación (cuando sea necesaria) de un parámetro para evitar calculo redundannte se conoce como llamadas por necesidad.

  33. Argumentos opcionales y por palabra clave En muchos LP los parámetros formales son asociados con los argumentos de acuerdo a su posición: El n-esimo parametro formal es asociado al n-esimo argumento. Es también posible establecer el paso de los argumentos por palabra clave tal y como ocurre en muchos comandos de algunos sistemas operativos (ej. dir /a:d cc –l pthread) • Con operandos por palabra clave es necesario recordar la palabra clave. • Con operandos por posición es necesario recordar la posición correspondiente a cada operando

  34. Argumentos opcionales y por palabra clave Existen lenguajes de programación que permiten establecer valores por omisión para ciertos argumentos. • conveniente para el caso en que el procedimiento se llama en repetidas ocasiones con el mismo valor para ese argumento.

  35. Argumentos opcionales y por palabra clave Para el caso de que los argumento que se pasen por posición es conveniente que los argumentos opcionales se pongan al final como en el caso de (lambda (n . m) …). Al utilizar paso de parámetros por palabra clave y argumentos opcionales solo se indicarían las palabras claves de aquellos argumentos obligatorios y de aquellos cuyo valor por omisión no nos convenga.

More Related