De Wikipedia, la enciclopedia libre
Saltar a navegación Saltar a búsqueda

En programación informática , una declaración de asignación establece y / o restablece el valor almacenado en la ubicación o ubicaciones de almacenamiento indicadas por un nombre de variable ; en otras palabras, copia un valor en la variable. En la mayoría de los lenguajes de programación imperativos , la declaración de asignación (o expresión) es una construcción fundamental.

Hoy en día, la notación más comúnmente utilizada para esta operación básica ha llegado a ser (originalmente Superplan 1949-51, popularizado por Fortran 1957 y C ) seguida de [1] (originalmente ALGOL 1958, popularizado por Pascal ), [2] aunque hay muchas otras notaciones en uso. En algunos idiomas, el símbolo utilizado se considera un operador (lo que significa que la declaración de asignación como un todo devuelve un valor) mientras que otros definen la asignación como una declaración (lo que significa que no se puede usar en una expresión).x = expr x := expr

Las asignaciones generalmente permiten que una variable tenga diferentes valores en diferentes momentos durante su vida útil y alcance . Sin embargo, algunos lenguajes (principalmente estrictamente funcionales ) no permiten ese tipo de reasignación "destructiva", ya que podría implicar cambios de estado no local. El propósito es hacer cumplir la transparencia referencial , es decir, funciones que no dependen del estado de algunas variables, pero que producen los mismos resultados para un conjunto dado de entradas paramétricas en cualquier momento. Los programas modernos en otros lenguajes también suelen utilizar estrategias similares, aunque menos estrictas, y solo en ciertas partes, con el fin de reducir la complejidad, normalmente junto con metodologías complementarias como la estructuración de datos ,programación estructurada y orientación a objetos .

Semántica [ editar ]

Una operación de asignación es un proceso en programación imperativa en el que diferentes valores se asocian con un nombre de variable particular a medida que pasa el tiempo. [1] El programa, en tal modelo, opera cambiando su estado usando sucesivas sentencias de asignación. [2] [3] Las primitivas de los lenguajes de programación imperativos dependen de la asignación para realizar la iteración . [4] En el nivel más bajo, la asignación se implementa utilizando operaciones de máquina como MOVEo STORE. [2] [4]

Las variables son contenedores de valores. Es posible poner un valor en una variable y luego reemplazarlo por uno nuevo. Una operación de asignación modifica el estado actual del programa en ejecución. [3] En consecuencia, la asignación depende del concepto de variables . En una tarea:

  • Se expressionevalúa en el estado actual del programa.
  • Se variablele asigna el valor calculado, reemplazando el valor anterior de esa variable.

Ejemplo: asumiendo que aes una variable numérica, la asignación a := 2*asignifica que el contenido de la variable ase duplica después de la ejecución de la declaración.

Un segmento de ejemplo de código C :

int  x  =  10 ;  flotar  y ; x  =  23 ; y  =  32,4f ;

En este ejemplo, la variable xse declara primero como un int y luego se le asigna el valor de 10. Observe que la declaración y la asignación ocurren en la misma instrucción. En la segunda línea, yse declara sin asignación. En la tercera línea, xse reasigna el valor de 23. Finalmente, yse asigna el valor de 32,4.

Para una operación de asignación, es necesario que el valor de la expressionestá bien definido (es un válido rvalue ) y que la variablerepresenta una entidad modificable (es un modificable válida (no const ) lvalue ). En algunos lenguajes, típicamente dinámicos , no es necesario declarar una variable antes de asignarle un valor. En tales lenguajes, una variable se declara automáticamente la primera vez que se le asigna, con el alcance que se declara variando según el idioma.

Asignación única [ editar ]

Cualquier asignación que cambie un valor existente (por ejemplo x := x + 1) no está permitida en lenguajes puramente funcionales . [4] En la programación funcional , se desaconseja la asignación en favor de la asignación única, también llamada inicialización . La asignación única es un ejemplo de vinculación de nombres y se diferencia de la asignación descrita en este artículo en que solo se puede realizar una vez, generalmente cuando se crea la variable; no se permite ninguna reasignación posterior.

Una evaluación de expresión no tiene un efecto secundario si no cambia un estado observable de la máquina, [5] y produce los mismos valores para la misma entrada. [4] La asignación imperativa puede introducir efectos secundarios mientras se destruye y hace que el valor antiguo no esté disponible mientras se sustituye por uno nuevo, [6] y se denomina asignación destructiva por esa razón en LISP y programación funcional , similar a la actualización destructiva .

La asignación única es la única forma de asignación disponible en lenguajes puramente funcionales, como Haskell , que no tienen variables en el sentido de lenguajes de programación imperativos [4], sino valores constantes nombrados posiblemente de naturaleza compuesta con sus elementos definidos progresivamente bajo demanda. . Los lenguajes puramente funcionales pueden brindar una oportunidad para que los cálculos se realicen en paralelo , evitando el cuello de botella de von Neumann de la ejecución secuencial de un paso a la vez, ya que los valores son independientes entre sí. [7]

Los lenguajes funcionales impuros proporcionan tanto una asignación única como una asignación verdadera (aunque la asignación verdadera se usa típicamente con menos frecuencia que en los lenguajes de programación imperativos). Por ejemplo, en Scheme, tanto la asignación única (con let) como la asignación verdadera (con set!) se pueden usar en todas las variables, y se proporcionan primitivas especializadas para la actualización destructiva dentro de listas, vectores, cadenas, etc. En OCaml, solo se permite una asignación única para variables, a través de la sintaxis; sin embargo, la actualización destructiva se puede utilizar en elementos de matrices y cadenas con un operador separado , así como en campos de registros y objetos que el programador ha declarado explícitamente mutables (es decir, capaces de ser cambiados después de su declaración inicial).let name = value<-

Los lenguajes de programación funcional que usan una sola asignación incluyen Clojure (para estructuras de datos, no vars), Erlang (acepta asignaciones múltiples si los valores son iguales, a diferencia de Haskell), F # , Haskell , JavaScript (para constantes), Lava , OCaml , Oz (para variables de flujo de datos, no celdas), Racket (para algunas estructuras de datos como listas, no símbolos), SASL , Scala (para vals), SISAL , ML estándar . El código de Prolog sin retroceso puede considerarse explícitoasignación única, explícita en el sentido de que sus variables (nombradas) pueden estar en estado explícitamente sin asignar, o establecerse exactamente una vez. En Haskell, por el contrario, no puede haber variables sin asignar, y se puede pensar que cada variable se establece implícitamente en su valor (o más bien en un objeto computacional que producirá su valor a pedido ) cuando se crea.

Valor de una tarea [ editar ]

En algunos lenguajes de programación, una instrucción de asignación devuelve un valor, mientras que en otros no.

En la mayoría de los lenguajes de programación orientados a expresiones (por ejemplo, C ), la declaración de asignación devuelve el valor asignado, permitiendo expresiones idiomáticas como x = y = a, en las que la declaración de asignación y = adevuelve el valor de a, que luego se asigna a x. En una declaración como , el valor de retorno de una función se usa para controlar un bucle mientras se asigna el mismo valor a una variable.while ((ch = getchar()) != EOF) {}

En otros lenguajes de programación, Scheme por ejemplo, el valor de retorno de una asignación no está definido y tales modismos no son válidos.

En Haskell , [8] no hay asignación de variables; pero las operaciones similares a la asignación (como asignar a un campo de una matriz o un campo de una estructura de datos mutable) generalmente evalúan el tipo de unidad , que se representa como (). Este tipo solo tiene un valor posible, por lo que no contiene información. Por lo general, es el tipo de expresión que se evalúa únicamente por sus efectos secundarios.

Formas variantes de asignación [ editar ]

Ciertos patrones de uso son muy comunes y, por lo tanto, a menudo tienen una sintaxis especial para respaldarlos. Estos son principalmente azúcar sintáctico para reducir la redundancia en el código fuente, pero también ayudan a los lectores del código a comprender la intención del programador y proporcionan al compilador una pista para una posible optimización.

Tarea aumentada [ editar ]

El caso en el que el valor asignado depende de uno anterior es tan común que muchos lenguajes imperativos, sobre todo C y la mayoría de sus descendientes, proporcionan operadores especiales llamados asignación aumentada , como *=, por a = 2*alo que en su lugar se pueden escribir como a *= 2. [3] Más allá del azúcar sintáctico, esto ayuda a la tarea del compilador al dejar en claro que la modificación in situ de la variable aes posible.

Tarea encadenada [ editar ]

Una declaración como w = x = y = zse llama asignación encadenada en la que el valor de zse asigna a múltiples variables w, x,y y. Las asignaciones encadenadas se utilizan a menudo para inicializar múltiples variables, como en

a = b = c = d = f = 0

No todos los lenguajes de programación admiten la asignación encadenada. Las asignaciones encadenadas equivalen a una secuencia de asignaciones, pero la estrategia de evaluación difiere entre los idiomas. Para asignaciones encadenadas simples, como inicializar múltiples variables, la estrategia de evaluación no importa, pero si los objetivos (valores l) en la asignación están conectados de alguna manera, la estrategia de evaluación afecta el resultado.

En algunos lenguajes de programación ( C por ejemplo), las asignaciones encadenadas son compatibles porque las asignaciones son expresiones y tienen valores. En este caso, la asignación en cadena se puede implementar con una asignación asociativa por la derecha , y las asignaciones ocurren de derecha a izquierda. Por ejemplo, i = arr[i] = f()es equivalente a arr[i] = f(); i = arr[i]. En C ++ también están disponibles para valores de tipos de clase al declarar el tipo de retorno apropiado para el operador de asignación.

En Python , las declaraciones de asignación no son expresiones y, por lo tanto, no tienen valor. En cambio, las asignaciones encadenadas son una serie de declaraciones con múltiples destinos para una sola expresión. Las asignaciones se ejecutan de izquierda a derecha para que i = arr[i] = f()evalúe la expresión f(), luego asigne el resultado al objetivo situado más a la izquierda i, y luego asigne el mismo resultado al siguiente objetivo arr[i], utilizando el nuevo valor de i. [9] Esto es esencialmente equivalente a, tmp = f(); i = tmp; arr[i] = tmpaunque no se produce una variable real para el valor temporal.

Asignación paralela [ editar ]

Algunos lenguajes de programación, como APL , Common Lisp , [10] Go , [11] JavaScript (desde 1.7), PHP , Maple , Lua , occam 2 , [12] Perl , [13] Python , [14] REBOL , Ruby , [15] y PowerShell permiten asignar varias variables en paralelo, con sintaxis como:

a, b: = 0, 1

que asigna simultáneamente 0 ay a1 a b. Esto se conoce con mayor frecuencia como asignación en paralelo ; fue introducido en CPL en 1963, bajo el nombre de asignación simultánea , [16] y algunas veces se le llama asignación múltiple , aunque esto es confuso cuando se usa con "asignación única", ya que no son opuestos. Si el lado derecho de la asignación es una sola variable (por ejemplo, una matriz o estructura), la característica se llama desempaquetar [17] o desestructuración de asignación : [18]

lista de var : = {0, 1}a, b: = lista

La lista se descomprimirá de modo que se asigne 0 ay a1 a b. Es más,

a, b: = b, a

intercambia los valores de ay b. En idiomas sin asignación paralela, esto debería escribirse para usar una variable temporal

var t: = aa: = bb: = t

ya que a := b; b := adeja ambos ay bcon el valor original de b.

Algunos lenguajes, como Go y Python, combinan asignación paralela, tuplas y desempaquetado automático de tuplas para permitir múltiples valores de retorno de una sola función, como en este ejemplo de Python,

def  f ():  return  1 ,  2 a ,  b  =  f ()

mientras que otros lenguajes, como C # , que se muestran aquí, requieren la construcción y deconstrucción de tuplas explícitas con paréntesis:

(a, b) = (b, a);
( cadena ,  int )  f ()  =>  ( "foo" ,  1 ); var  ( a ,  b )  =  f ();

Esto proporciona una alternativa al uso de parámetros de salida para devolver múltiples valores de una función. Esto se remonta a CLU (1974), y CLU ayudó a popularizar la asignación paralela en general.

Además, C # permite la asignación de deconstrucción generalizada con la implementación definida por la expresión del lado derecho, ya que el compilador busca una instancia apropiada o un método de extensión Deconstruct en la expresión, que debe tener parámetros de salida para las variables a las que se asignan. [19] Por ejemplo, uno de esos métodos que daría a la clase que aparece en el mismo comportamiento que el valor de retorno f()anterior sería

void  Deconstruct ( fuera de la  cadena  a ,  fuera del  int  b )  {  a  =  "foo" ;  b  =  1 ;  }

En C y C ++, el operador de coma es similar a la asignación paralela al permitir que ocurran múltiples asignaciones dentro de una sola declaración, escribiendo en a = 1, b = 2lugar de a, b = 1, 2. Esto se usa principalmente en bucles for y se reemplaza por asignación paralela en otros idiomas como Go. [20] Sin embargo, el código C ++ anterior no asegura una simultaneidad perfecta, ya que el lado derecho del siguiente código a = b, b = a+1se evalúa después del lado izquierdo. En lenguajes como Python, a, b = b, a+1asignará las dos variables al mismo tiempo, utilizando el valor inicial de a para calcular el nuevo b.

Asignación versus igualdad [ editar ]

El uso del signo igual =como operador de asignación ha sido criticado con frecuencia, debido al conflicto con iguales como comparación para la igualdad. Esto resulta tanto en confusión para los principiantes al escribir código como en confusión incluso para programadores experimentados en la lectura de código. El uso de iguales para la asignación se remonta al Superplan de lenguaje de Heinz Rutishauser , diseñado entre 1949 y 1951, y fue particularmente popularizado por Fortran:

Un ejemplo notorio de una mala idea fue la elección del signo igual para denotar la asignación. Se remonta a Fortran en 1957 [a] y ha sido copiada a ciegas por ejércitos de diseñadores de lenguajes. por qué es una mala idea? Porque derroca una tradición centenaria dejar que “=” denote una comparación para la igualdad, un predicado que es verdadero o falso. Pero Fortran lo hizo para significar asignación, el cumplimiento de la igualdad. En este caso, los operandos están en pie de igualdad: el operando izquierdo (una variable) se igualará al operando derecho (una expresión). x = y no significa lo mismo que y = x. [21]

-  Niklaus Wirth , Buenas ideas, a través del espejo

Los programadores principiantes a veces confunden la asignación con el operador relacional para la igualdad, ya que "=" significa igualdad en matemáticas y se usa para la asignación en muchos idiomas. Pero la asignación altera el valor de una variable, mientras que la prueba de igualdad comprueba si dos expresiones tienen el mismo valor.

En algunos lenguajes, como BASIC , "="se usa un solo signo igual ( ) tanto para el operador de asignación como para el operador relacional de igualdad, y el contexto determina a qué se refiere. Otros idiomas usan símbolos diferentes para los dos operadores. Por ejemplo:

  • En ALGOL y Pascal , el operador de asignación es un signo de dos puntos y un signo igual ( ":=") mientras que el operador de igualdad es un único igual ( "=").
  • En C , el operador de asignación es un solo signo igual ( "=") mientras que el operador de igualdad es un par de signos iguales ( "==").
  • En R , el operador de asignación es básicamente <-, como en x <- value, pero se puede usar un solo signo igual en ciertos contextos.

La similitud en los dos símbolos puede conducir a errores si el programador olvida qué forma (" =", " ==", " :=") es apropiada, o escribe incorrectamente " =" cuando " ==" estaba previsto. Este es un problema de programación común con lenguajes como C (incluido un famoso intento de puerta trasera del kernel de Linux), [22] donde el operador de asignación también devuelve el valor asignado (de la misma manera que una función devuelve un valor), y puede estar anidadas válidamente dentro de las expresiones. Si la intención era comparar dos valores en una ifdeclaración, por ejemplo, es muy probable que una asignación devuelva un valor interpretable como booleano verdadero, en cuyo caso la thencláusula se ejecutará, lo que hará que el programa se comporte de manera inesperada.Algunos procesadores de idiomas (comogcc ) puede detectar tales situaciones y advertir al programador del posible error.

Notación [ editar ]

Las dos representaciones más comunes para la asignación de copia son el signo igual ( =) y los dos puntos iguales ( :=). Ambas formas pueden denotar semánticamente una declaración de asignación o un operador de asignación (que también tiene un valor), según el idioma y / o el uso.

Otras posibilidades incluyen una flecha hacia la izquierda o una palabra clave, aunque hay otras variantes más raras:

Las asignaciones de pseudocódigo matemático generalmente se representan con una flecha hacia la izquierda.

Algunas plataformas ponen la expresión a la izquierda y la variable a la derecha:

Algunos lenguajes orientados a expresiones, como Lisp [31] [32] y Tcl, usan uniformemente la sintaxis de prefijo (o sufijo) para todas las declaraciones, incluida la asignación.

Ver también [ editar ]

  • Operador de asignación en C ++
  • Operador (programación)
  • Vinculación de nombre
  • Unificación (informática)
  • Objeto inmutable
  • Const-corrección

Notas [ editar ]

  1. ↑ El uso de=es anterior a Fortran, aunque fue popularizado por Fortran.

Referencias [ editar ]

  1. ^ a b "2cs24 declarativo" . www.csc.liv.ac.uk . Archivado desde el original el 24 de abril de 2006 . Consultado el 20 de abril de 2018 .
  2. ^ a b c "Programación imperativa" . uah.edu . Consultado el 20 de abril de 2018 .
  3. ↑ a b c Ruediger-Marcus Flaig (2008). Programación bioinformática en Python: un curso práctico para principiantes . Wiley-VCH. págs. 98–99. ISBN 978-3-527-32094-3. Consultado el 25 de diciembre de 2010 .
  4. ^ a b c d e Cruzando fronteras: Explore la programación funcional con Haskell Archivado el 19 de noviembre de 2010 en Wayback Machine , por Bruce Tate
  5. ^ Mitchell, John C. (2003). Conceptos en lenguajes de programación . Prensa de la Universidad de Cambridge. pag. 23. ISBN 978-0-521-78098-8. Consultado el 3 de enero de 2011 .
  6. ^ "Lenguajes de programación imperativos (IPL)" (PDF) . gwu.edu . Consultado el 20 de abril de 2018 .
  7. ^ John C. Mitchell (2003). Conceptos en lenguajes de programación . Prensa de la Universidad de Cambridge. págs. 81–82. ISBN 978-0-521-78098-8. Consultado el 3 de enero de 2011 .
  8. ^ Hudak, Paul (2000). La escuela de expresión Haskell: aprendizaje de la programación funcional a través de multimedia . Cambridge: Cambridge University Press. ISBN 0-521-64408-9.
  9. ^ "7. Declaraciones simples - documentación de Python 3.6.5" . docs.python.org . Consultado el 20 de abril de 2018 .
  10. ^ "CLHS: Macro SETF, PSETF" . Común Lisp Hyperspec . LispWorks . Consultado el 23 de abril de 2019 .
  11. ^ La especificación del lenguaje de programación Go: asignaciones
  12. ^ INMOS Limited, ed. (1988). Manual de referencia de Occam 2 . Nueva Jersey: Prentice Hall. ISBN 0-13-629312-3.
  13. ^ Pared, Larry ; Christiansen, Tom; Schwartz, Randal C. (1996). Lenguaje de programación Perl (2 ed.). Cambridge: O´Reilly. ISBN 1-56592-149-6.
  14. ^ Lutz, Mark (2001). Lenguaje de programación Python (2 ed.). Sebastopol: O´Reilly. ISBN 0-596-00085-5.
  15. ^ Tomás, David; Hunt, Andrew (2001). Programación de Ruby: la guía pragmática del programador . Río Upper Saddle: Addison Wesley. ISBN 0-201-71089-7.
  16. ^ DW Barron y col. , "Las principales características de CPL", Computer Journal 6 : 2: 140 (1963). texto completo (suscripción)
  17. ^ "PEP 3132 - Desembalaje iterable extendido" . legacy.python.org . Consultado el 20 de abril de 2018 .
  18. ^ "Cesión de desestructuración" . Documentos web de MDN . Consultado el 20 de abril de 2018 .
  19. ^ "Deconstrucción de tuplas y otros tipos" . Microsoft Docs . Microsoft . Consultado el 29 de agosto de 2019 .
  20. ^ Effective Go : for , "Finalmente, Go no tiene un operador de coma y ++ y - son declaraciones, no expresiones. Por lo tanto, si desea ejecutar varias variables en un for, debe usar la asignación en paralelo (aunque eso excluye ++ y - ). "
  21. ^ Niklaus Wirth. "Buenas ideas, a través del espejo". CiteSeerX 10.1.1.88.8309 .  Falta o vacío |url=( ayuda )
  22. ^ Corbet (6 de noviembre de 2003). "Un intento de puerta trasera del kernel" .
  23. ^ Moore, Lawrie (1980). Fundamentos de la programación con Pascal . Nueva York: John Wiley & Sons. ISBN 0-470-26939-1.
  24. ^ Meyer, Bertrand (1992). Eiffel el idioma . Hemel Hempstead: Prentice Hall International (Reino Unido). ISBN 0-13-247925-7.
  25. ^ Wiener, Richard (1996). Una introducción a la informática orientada a objetos utilizando Eiffel . Upper Saddle River, Nueva Jersey: Prentice Hall. ISBN 0-13-183872-5.
  26. ^ Feinberg, Neal; Keene, Sonya E .; Mathews, Robert O .; Withington, P. Tucker (1997). Programación Dylan . Massachusetts: Addison Wesley. ISBN 0-201-47976-1.
  27. ^ "PEP 572 - Expresiones de asignación" . python.org . 28 de febrero de 2018 . Consultado el 4 de marzo de 2020 .
  28. ^ "La especificación del lenguaje de programación Go - El lenguaje de programación Go" . golang.org . Consultado el 20 de abril de 2018 .
  29. ^ Ullman, Jeffrey D. (1998). Elementos de programación ML: Edición ML97 . Englewood Cliffs, Nueva Jersey: Prentice Hall. ISBN 0-13-790387-1.
  30. ^ Iverson, Kenneth E. (1962). Un lenguaje de programación . John Wiley e hijos. ISBN 0-471-43014-5. Archivado desde el original el 4 de junio de 2009 . Consultado el 9 de mayo de 2010 .
  31. ^ Graham, Paul (1996). ANSI Common Lisp . Nueva Jersey: Prentice Hall. ISBN 0-13-370875-6.
  32. ^ Steele, Guy L. (1990). Common Lisp: El lenguaje . Lexington: Prensa digital. ISBN 1-55558-041-6.
  33. ^ Dybvig, R. Kent (1996). El lenguaje de programación del esquema: esquema ANSI . Nueva Jersey: Prentice Hall. ISBN 0-13-454646-6.
  34. ^ Smith, Jerry D. (1988). Introducción a Scheme . Nueva Jersey: Prentice Hall. ISBN 0-13-496712-7.
  35. ^ Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie (1996). Estructura e interpretación de programas informáticos . Nueva Jersey: McGraw-Hill. ISBN 0-07-000484-6.