En informática , se dice que una operación, función o expresión tiene un efecto secundario si modifica algún valor de variable de estado fuera de su entorno local, es decir, tiene un efecto observable además de devolver un valor (el efecto principal) a el invocador de la operación. Los datos de estado actualizados "fuera" de la operación pueden mantenerse "dentro" de un objeto con estado o de un sistema con estado más amplio dentro del cual se realiza la operación. Los efectos secundarios de ejemplo incluyen modificar una variable no local , modificar una variable local estática , modificar un argumento mutable pasado por referencia , realizar E / So llamando a otras funciones de efectos secundarios. [1] En presencia de efectos secundarios, el comportamiento de un programa puede depender de la historia; es decir, el orden de evaluación es importante. Comprender y depurar una función con efectos secundarios requiere conocimiento sobre el contexto y sus posibles historias. [2] [3]
El grado en que se utilizan los efectos secundarios depende del paradigma de programación. La programación imperativa se usa comúnmente para producir efectos secundarios, para actualizar el estado de un sistema. Por el contrario, la programación declarativa se usa comúnmente para informar sobre el estado del sistema, sin efectos secundarios.
En la programación funcional , los efectos secundarios rara vez se utilizan. La falta de efectos secundarios facilita la realización de verificaciones formales de un programa. Los lenguajes funcionales como Standard ML , Scheme y Scala no restringen los efectos secundarios, pero es habitual que los programadores los eviten. [4] El lenguaje funcional Haskell expresa efectos secundarios como E / S y otros cálculos con estado utilizando acciones monádicas . [5] [6]
Los programadores en lenguaje ensamblador deben ser conscientes de los efectos secundarios ocultos : instrucciones que modifican partes del estado del procesador que no se mencionan en el mnemónico de la instrucción. Un ejemplo clásico de un efecto secundario oculto es una instrucción aritmética que modifica implícitamente los códigos de condición (un efecto secundario oculto) mientras que modifica explícitamente un registro (el efecto manifiesto). Un posible inconveniente de un conjunto de instrucciones con efectos secundarios ocultos es que, si muchas instrucciones tienen efectos secundarios en un solo estado, como los códigos de condición, la lógica necesaria para actualizar ese estado secuencialmente puede convertirse en un cuello de botella en el rendimiento. El problema es particularmente agudo en algunos procesadores diseñados con canalización (desde 1990) o con ejecución fuera de orden . Tal procesador puede requerir circuitos de control adicionales para detectar efectos secundarios ocultos y detener la tubería si la siguiente instrucción depende de los resultados de esos efectos.
Transparencia referencial
La ausencia de efectos secundarios es una condición necesaria, pero no suficiente, para la transparencia referencial. La transparencia referencial significa que una expresión (como una llamada a una función) se puede reemplazar por su valor. Esto requiere que la expresión sea pura , es decir, la expresión debe ser determinista (siempre dé el mismo valor para la misma entrada) y libre de efectos secundarios.
Efectos secundarios temporales
Los efectos secundarios causados por el tiempo que tarda una operación en ejecutarse generalmente se ignoran cuando se discuten los efectos secundarios y la transparencia referencial. Hay algunos casos, como con la sincronización o las pruebas de hardware, en los que las operaciones se insertan específicamente para sus efectos secundarios temporales, por ejemplo, sleep(5000)
o for (int i = 0; i < 10000; ++i) {}
. Estas instrucciones no cambian de estado más que tomar una cantidad de tiempo para completarse.
Idempotencia
Se f
dice que una función con efectos secundarios es idempotente en composición secuencial f; f
si, cuando se llama dos veces con la misma lista de argumentos, la segunda llamada no tiene efectos secundarios y devuelve el mismo valor que la primera llamada [ cita requerida ] (asumiendo que no hay otros procedimientos fueron llamados entre el final de la primera llamada y el comienzo de la segunda llamada).
Por ejemplo, considere el siguiente código de Python :
x = 0def setx ( n ): global x x = nsetx ( 5 ) setx ( 5 )
Aquí, setx
es idempotente porque la segunda llamada a setx
(con el mismo argumento) no cambia el estado visible del programa: x
ya se estableció en 5 en la primera llamada, y nuevamente se establece en 5 en la segunda llamada, manteniendo así el mismo valor. Tenga en cuenta que esto es distinto de la idempotencia en la composición de funciones f ∘ f
. Por ejemplo, el valor absoluto es idempotente en la composición de funciones:
def abs ( n ): if n < 0 : return - n else : return nabs ( - 5 ) == abs ( abs ( - 5 )) == abs ( 5 ) == 5
Ejemplo
Una demostración común del comportamiento de los efectos secundarios es la del operador de asignación en C ++ . Por ejemplo, la asignación devuelve el operando derecho y tiene el efecto secundario de asignar ese valor a una variable. Esto permite una asignación múltiple sintácticamente limpia:
int i , j ; i = j = 3 ;
Debido a que el operador se asocia a la derecha , esto equivale a
int i , j ; i = ( j = 3 ); // j = 3 devuelve 3, que luego se asigna a i
Donde el resultado de asignar 3 en j
luego se asigna a i
. Esto presenta un problema potencial para los programadores novatos que pueden confundir
while ( b == 10 ) {} // prueba si b se evalúa como 10
con
while ( b = 10 ) {} // = devuelve 10 que se convierte automáticamente en verdadero, por lo que la prueba siempre es verdadera
Ver también
Referencias
- ^ Spuler, David A .; Sajeev, ASM (enero de 1994). "Detección del compilador de efectos secundarios de llamadas a funciones". Universidad James Cook. CiteSeerX 10.1.1.70.2096 .
El término efecto secundario se refiere a la modificación del entorno no local. Generalmente esto sucede cuando una función (o un procedimiento) modifica una variable global o argumentos pasados por parámetros de referencia. Pero aquí hay otras formas en las que se puede modificar el entorno no local. Consideramos las siguientes causas de efectos secundarios a través de una llamada de función: 1. Realización de E / S. 2. Modificación de variables globales. 3. Modificar variables permanentes locales (como variables estáticas en C). 4. Modificar un argumento pasado por referencia. 5. Modificar una variable local, ya sea automática o estática, de una función más arriba en la secuencia de llamada de función (generalmente a través de un puntero).
Cite journal requiere|journal=
( ayuda ) - ^ "Temas de investigación en programación funcional" ed. D. Turner, Addison-Wesley, 1990, págs. 17–42. Obtenido de: Hughes, John, Por qué importa la programación funcional (PDF)
- ^ Collberg, CSc 520 Principios de lenguajes de programación , Departamento de Ciencias de la Computación, Universidad de Arizona
- ^ Matthias Felleisen et al., Cómo diseñar programas , MIT Press
- ^ Informe Haskell 98, http://www.haskell.org .
- ^ Programación funcional imperativa , Simon Peyton Jones y Phil Wadler, Registro de la conferencia del 20º Simposio anual de ACM sobre principios de lenguajes de programación , páginas 71–84, 1993