Efecto secundario (informática)
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, si tiene algún efecto observable distinto de su efecto principal de devolver un valor al invocador de la operación. Los efectos secundarios de ejemplo incluyen la modificación de una variable no local, la modificación de una variable local estática, la modificación de un argumento mutable pasado por referencia, la realización de E/S o la llamada a otras funciones con efectos secundarios. En presencia de efectos secundarios, el comportamiento de un programa puede depender de la historia; es decir, el orden de evaluación importa. Comprender y depurar una función con efectos secundarios requiere conocimiento sobre el contexto y sus posibles historias.
Los efectos secundarios juegan un papel importante en el diseño y análisis de los lenguajes de programación. El grado en que se utilizan los efectos secundarios depende del paradigma de programación. Por ejemplo, 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.
La programación funcional tiene como objetivo minimizar o eliminar los efectos secundarios. La falta de efectos secundarios facilita la verificación formal de un programa. El lenguaje funcional Haskell elimina efectos secundarios como E/S y otros cálculos con estado reemplazándolos con acciones monádicas. Los lenguajes funcionales como Standard ML, Scheme y Scala no restringen los efectos secundarios, pero es habitual que los programadores los eviten.
Los programadores del lenguaje ensamblador deben ser conscientes de los efectos secundarios ocultos: instrucciones que modifican partes del estado del procesador que no se mencionan en el mnemotécnico 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 modifica explícitamente un registro (el efecto deseado). Un inconveniente potencial de un conjunto de instrucciones con efectos secundarios ocultos es que, si muchas instrucciones tienen efectos secundarios en un solo estado, como códigos de condición, entonces la lógica requerida para actualizar ese estado secuencialmente puede convertirse en un cuello de botella en el rendimiento. El problema es particularmente grave en algunos procesadores diseñados con canalización (desde 1990) o con ejecución desordenada. Dicho procesador puede requerir un circuito de control adicional 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 de función) se puede reemplazar con su valor. Esto requiere que la expresión sea pura, es decir, la expresión debe ser determinista (siempre dar el mismo valor para la misma entrada) y libre de efectos secundarios.
Efectos secundarios temporales
Los efectos secundarios causados por el tiempo que tarda en ejecutarse una operación generalmente se ignoran cuando se analizan los efectos secundarios y la transparencia referencial. Hay algunos casos, como con la temporización o las pruebas de hardware, donde las operaciones se insertan específicamente por sus efectos secundarios temporales, p. 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 completarlas.
Impotencia
Una subrutina con efectos secundarios es idempotente si múltiples aplicaciones de la subrutina tienen el mismo efecto en el estado del sistema que una sola aplicación, en otras palabras, si la función del espacio de estado del sistema asociada con la subrutina es idempotente en el sentido matemático. Por ejemplo, considere el siguiente programa de Python:
x = 0def setx()n): mundial x x = nsetx()3)afirmación x == 3setx()3)afirmación x == 3
setx
es idempotente porque la segunda aplicación de setx
a 3 tiene el mismo efecto en el estado del sistema que la primera aplicación: x
fue ya establecido en 3 después de la primera aplicación, y todavía está establecido en 3 después de la segunda aplicación.
Una función pura es idempotente si es idempotente en el sentido matemático. Por ejemplo, considere el siguiente programa de Python:
def abdominales()n): retorno -n si n . 0 más nafirmación abdominales()abdominales()-3) == abdominales()-3)
abs
es idempotente porque la segunda aplicación de abs
al valor de retorno de la primera aplicación a -3 devuelve el mismo valor que la primera aplicación a -3.
Ejemplo
Una demostración común del comportamiento de los efectos secundarios es la del operador de asignación en C. La asignación a = b
es una expresión que se evalúa con el mismo valor que la expresión b
, con el efecto secundario de almacenar el valor R de b
en el valor L de a
. Esto permite la asignación múltiple:
a = ()b = 3); // b = 3 evalúa a 3, que luego se asigna a un
Debido a que el operador derecho asocia, esto es equivalente a
a = b = 3;
Esto presenta un problema potencial para los programadores novatos que pueden confundir
mientras ()b == 3) {} // pruebas si b evalúa a 3
con
mientras ()b = 3) {} // b = 3 evalúa a 3, que luego arroja a la verdad para que el bucle sea infinito
Contenido relacionado
Datos (informática)
Ratón óptico
Codificador de voz