Estou tentando entender por que ter uma variável local ou um loop for dentro de uma função não é considerado pura programação funcional.
Dada esta função:
int as_int(char *str)
{
int acc; /* accumulate the partial result */
for (acc = 0; isdigit(*str); str++) {
acc = acc * 10 + (*str - '0');
}
return acc;
}
Em que circunstâncias a variável acc seria um efeito colateral? Mesmo em um ambiente simultâneo, cada chamada da função teria sua própria cópia de acc. Portanto, não entendo por que isso não é permitido na programação funcional.
functional-programming
loops
side-effect
tomatoRadar
fonte
fonte
as_int
é uma função pura, mas o código nela não é puro.acc
é mutável.Respostas:
Looping na programação funcional não é feito com instruções de controle, como
for
ewhile
, é feito com chamadas explícitas para funções comomap
,fold
ou recursão - todos os quais envolvem colocando a chamada loop interno dentro de outra função . Se o código do loop alterar variáveis fora do loop, essa função de loop interno manipulará variáveis fora de seu escopo e, portanto, será impura . Portanto, toda a função externa é pura, mas o loop não é. As construções em loop na programação funcional exigem que você explique o estado. A conversão do seu código para algo usando ferramentas de loop de programação funcional revela a impureza:(Observação: essa sintaxe é aproximada para transmitir a ideia geral)
Esse código usa uma função interna para o corpo do loop, que deve alterar a variável
acc
, que está fora do escopo. Isso é impuro - a função do loop interno depende do contexto do loop externo , chamando-o várias vezes com o mesmo caractere terá efeitos colaterais, e a ordem em que você o chama na sequência de caracteres é importante. Na programação funcional, para tornar isso uma função pura, é necessário tornar explícita essa dependência do estado passado entre iterações de loop comfold
:fold
usa uma função de dois argumentos para o corpo do loop interno: o primeiro argumento é um item na sequência quefold
está sendo repetida, enquanto o segundo é algum valor que o corpo do loop interno usa para criar resultados parciais. Para a primeira iteração do loop,acc
é 0, para o segundo,acc
qualquer que seja a primeira chamada de função do loop interno retornada, para o terceiro, seja qual for o segundo loop interno retornado, e o loop final retorna o resultado de toda afold
expressão.Observe que isso não é realmente um problema com o seu código da perspectiva do resto do seu programa - ambas as definições de
as_int
são puras. A diferença é que, ao tornar o código do loop interno uma função pura, você pode aproveitar a enorme variedade de ferramentas que a programação funcional oferece para decompor o loop em algo mais declarativo (por exemplo, usando takeWhile, fold, filter, map, etc. etc.)fonte
takeWhile
,fold
,filter
,map
, (estilo ou seja declarativa) é que você também pensar parada em termos de "Compute algo por posições de memória atualização destrutiva". Dessa maneira, o resultado não depende da história / sequência exata das etapas de cálculo.