Looping na programação funcional não é feito com instruções de controle, como for
e while
, é feito com chamadas explícitas para funções como map
, 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:
int as_int(char *str)
{
int acc = 0; /* accumulate the partial result */
map(takeWhile(isdigit, str), void function(char *chr) {
acc = acc * 10 + (chr - '0');
});
return acc;
}
(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 com fold
:
int as_int(char *str)
{
return fold(takeWhile(isdigit, str), 0, int function(char *chr, int acc) {
return acc * 10 + (chr - '0');
});
}
fold
usa uma função de dois argumentos para o corpo do loop interno: o primeiro argumento é um item na sequência que fold
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 a fold
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.)