En informática , se dice que una operación o expresión tiene un efecto secundario si tiene algún efecto observable distinto de su efecto principal de leer el valor de sus argumentos y devolver un valor al invocador de la operación. Ejemplos de efectos secundarios incluyen la modificación de una variable no local , una variable local estática o un argumento mutable pasado por referencia ; la realización de E/S ; o la llamada a otras funciones con efectos secundarios. [ 1 ] En presencia de efectos secundarios, el comportamiento de un programa puede depender del historial; es decir, el orden de evaluación importa. Comprender y depurar una función con efectos secundarios requiere conocimiento del contexto y sus posibles historiales. [ 2 ] [ 3 ] Los efectos secundarios desempeñan un papel importante en el diseño y análisis de 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 busca minimizar o eliminar los efectos secundarios. La ausencia de efectos secundarios facilita la verificación formal de un programa. El lenguaje funcional Haskell elimina los efectos secundarios, como la E/S y otros cálculos con estado, reemplazándolos por acciones monádicas . [ 4 ] [ 5 ] Los lenguajes funcionales como Standard ML , Scheme y Scala no restringen los efectos secundarios, pero es habitual que los programadores los eviten. [ 6 ]
Los sistemas de efectos extienden los tipos para realizar un seguimiento de los efectos, lo que permite una notación concisa para las funciones con efectos, a la vez que se mantiene información sobre el alcance y la naturaleza de los efectos secundarios. En particular, las funciones sin efectos corresponden a funciones puras.
Los programadores de lenguaje ensamblador deben tener en cuenta los efectos secundarios ocultos : instrucciones que modifican partes del estado del procesador que no se mencionan en su mnemónico. Un ejemplo clásico de 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 previsto). Una posible desventaja de un conjunto de instrucciones con efectos secundarios ocultos es que, si muchas instrucciones tienen efectos secundarios sobre una sola parte del 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 grave en algunos procesadores diseñados con segmentación (desde 1990) o con ejecución fuera de orden . Dicho procesador puede requerir circuitos de control adicionales para detectar efectos secundarios ocultos y detener la segmentación 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 implica que una expresión (como una función) puede sustituirse por su valor. Esto requiere que la expresión sea pura , es decir, que sea determinista (que siempre produzca el mismo valor para la misma entrada) y que no tenga efectos secundarios.
Efectos secundarios temporales
Los efectos secundarios causados por el tiempo que tarda en ejecutarse una operación suelen ignorarse al hablar de efectos secundarios y transparencia referencial. Hay algunos casos, como en la medición del tiempo o las pruebas de hardware, donde las operaciones se insertan específicamente por sus efectos secundarios temporales, por ejemplo, sleep(5000)o for (int i = 0; i < 10000; ++i) {}. Estas instrucciones no cambian el estado más allá de tardar un tiempo en completarse.
Idempotencia
Una subrutina con efectos secundarios es idempotente si múltiples llamadas a la subrutina tienen el mismo efecto sobre el estado del sistema que una sola llamada; en otras palabras, si la función del espacio de estados del sistema hacia sí misma asociada con la subrutina es idempotente en el sentido matemático . Por ejemplo, considere el siguiente programa en Python :
x = 0def setx ( n ): global x x = nsetx ( 3 ) assert x == 3 setx ( 3 ) assert x == 3setxes idempotente porque la segunda llamada a setx3 tiene el mismo efecto en el estado del sistema que la primera llamada: xya estaba establecido en 3 después de la primera llamada, y sigue establecido en 3 después de la segunda llamada.
Una función pura es idempotente si lo es en el sentido matemático . Por ejemplo, considere el siguiente programa en Python:
def abs ( n ) : return -n if n < 0 else nafirmar abs ( abs ( - 3 )) == abs ( - 3 )abses idempotente porque la segunda llamada al absvalor de retorno de la primera llamada a -3 devuelve el mismo valor que la primera llamada a -3.
Ejemplo
Una demostración común del comportamiento de efecto secundario es la del operador de asignación en C. La asignación a = bes una expresión que se evalúa al mismo valor que la expresión b, con el efecto secundario de almacenar el valor R de ben el valor L de a. Esto permite la asignación múltiple:
a = ( b = 3 ); // b = 3 se evalúa como 3, que luego se asigna a aDebido a que el operador tiene derechos asociados , esto es equivalente a
a = b = 3 ;Esto representa un posible obstáculo para los programadores novatos que pueden confundirse.
while ( b == 3 ) {} // comprueba si b se evalúa como 3con
while ( b = 3 ) {} // b = 3 se evalúa como 3, que luego se convierte a verdadero, por lo que el bucle es infinito.Véase también
Referencias
- ↑ Spuler, David A.; Sajeev, A. Sayed Muhammed (enero de 1994). Compiler Detection of Function Call Side Effects . James Cook University . CiteSeerX 10.1.1.70.2096 .
El término efecto secundario se refiere a la modificación del entorno no local. Generalmente esto ocurre 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 que el entorno no local puede ser modificado. Consideramos las siguientes causas de efectos secundarios a través de una llamada a función: 1. Realizar E/S. 2. Modificar 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 a función (generalmente a través de un puntero).
- ↑ Turner, David A. , ed. (1990). Temas de investigación en programación funcional . Addison-Wesley . págs. 17–42 . Por Hughes, John. "Por qué importa la programación funcional" (PDF) . Archivado (PDF) del original el 14 de junio de 2022. Consultado el 6 de agosto de 2022 .
- ↑ Collberg, Christian S. (22 de abril de 2005). "CSc 520 Principios de los lenguajes de programación" . Departamento de Ciencias de la Computación, Universidad de Arizona . Archivado del original el 6 de agosto de 2022. Consultado el 6 de agosto de 2022 .
- ↑ "Informe Haskell 98" . 1998.
- ↑ Jones, Simon Peyton; Wadler, Phil (1993). Programación funcional imperativa . Actas del 20.º Simposio Anual de la ACM sobre Principios de Lenguajes de Programación. págs. 71–84 .
- ↑ Felleisen, Matthias ; Findler, Robert Bruce; Flatt, Matthew; Krishnamurthi, Shriram (2014-08-01). "Cómo diseñar programas" (2.ª ed.). MIT Press .
- Programación informática
- teoría de lenguajes de programación
- Programación funcional