Estoy tratando de entender por qué tener una variable local o un bucle for dentro de una función no se considera una programación puramente funcional.
Dada esta función:
int as_int(char *str)
{
int acc; /* accumulate the partial result */
for (acc = 0; isdigit(*str); str++) {
acc = acc * 10 + (*str - '0');
}
return acc;
}
¿En qué circunstancias la variable acc sería un efecto secundario? Incluso en un entorno concurrente, cada invocación de la función tendría su propia copia de acc. Así que no entiendo por qué no está permitido en la programación funcional.
functional-programming
loops
side-effect
tomateRadar
fuente
fuente
as_int
es una función pura, pero el código que contiene no es puro.acc
es mutableRespuestas:
Looping en la programación funcional no se hace con las sentencias de control como
for
ywhile
, se hace con llamadas explícitas a funciones comomap
,fold
o recursividad - todos los cuales implican la colocación de la llamada bucle interno dentro de otra función . Si el código del bucle muta variables fuera del bucle, esta función del bucle interno estaría manipulando variables fuera de su alcance y, por lo tanto, sería impuro . Entonces, toda la función externa es pura, pero el bucle no lo es. Las construcciones de bucle en la programación funcional requieren que haga explícito el estado. Traducir su código a algo utilizando herramientas de bucle de programación funcional revela la impureza:(Nota: esta sintaxis es aproximada para transmitir la idea general)
Este código usa una función interna para el cuerpo del bucle que debe mutar la variable
acc
, que está fuera de su alcance. Esto es impuro: la función del bucle interno depende del contexto del bucle externo , llamarlo varias veces con el mismo carácter tendrá efectos secundarios, y el orden en que se llama en la secuencia de caracteres es importante. En la programación funcional, para hacer de esto una función pura, tendría que hacer explícita esta dependencia del estado pasado entre iteraciones de bucle confold
:fold
utiliza una función de dos argumentos para el cuerpo del bucle interno: el primer argumento es un elemento de la secuencia quefold
se repite, mientras que el segundo es algún valor que el cuerpo del bucle interno utiliza para generar resultados parciales. Para la primera iteración del bucle,acc
es 0, para el segundo,acc
es lo que sea que haya devuelto la primera llamada de función del bucle interno, para el tercero, sea lo que haya devuelto el segundo bucle interno, y el bucle final devuelve el resultado de toda lafold
expresión.Tenga en cuenta que esto no es realmente un problema con su código desde la perspectiva del resto de su programa: ambas definiciones
as_int
son puras. La diferencia es que al hacer que el código del bucle interno sea una función pura, puede aprovechar la gran variedad de herramientas que ofrece la programación funcional para descomponer el bucle en algo más declarativo (por ejemplo, usando takeWhile, fold, filter, map, etc., etc.)fuente
takeWhile
,fold
,filter
,map
, (es decir, estilo declarativo) es que también dejar de pensar en términos de "Calcular algo por las posiciones de memoria de actualización destructiva". De esta manera, el resultado no depende del historial / secuencia exacta de los pasos de cálculo.