Reflexões Funcionais com Julia Language — Parte 2
Explorando a programação funcional com Julia (Parte 2)
Em meu artigo anterior Functional Musing with Julia Language — Part 1 , apresentei alguns conceitos básicos para começar a pensar funcionalmente com Julia. Agora continuamos essa exploração com mais alguns conceitos.
Para a segunda parte de nossas reflexões funcionais com Julia, vamos nos aprofundar em alguns dos conceitos avançados de programação funcional que podem ser implementados em Julia. Um conceito frequentemente usado na programação funcional é a recursão, que envolve a definição de uma função em termos dela mesma.
Recursão
Consideremos primeiro a seguinte função, escrita como imperativa, sem uso de recursão:
A função acima funciona como esperado. No entanto, há algumas coisas acontecendo que eu gostaria de apontar: O loop for modifica a variável `i`. Variables ae baté mesmo o próprio array são modificados a cada iteração. Estes são considerados efeitos colaterais, que abordamos na primeira parte deste artigo. Na programação funcional, queremos realizar coisas retornando valores de funções, em vez de modificar o estado.
Então, como podemos escrever a função acima de uma maneira mais funcional? Podemos usar recursão:
Outro conceito que não é muito falado, mas é fundamental para entender e programar funções corretamente: ramificações if-then-else e avaliação de argumentos de função.
Uma reviravolta funcional
Considere a seguinte função fatorial, escrita recursivamente:
Se chamarmos essa função, ela retornará conforme o esperado. Também podemos verificar o valor de retorno, pois é a primeira vez que o usamos:
Agora aqui está a reviravolta. Quero usar minha própria função if-then-else, então decido escrever:
À primeira vista, a função if acima parece estar ok, embora um pouco boba e ingênua. Parece que é apenas um wrapper em torno do ramo if normal.
Vou modificar a função fatorial acima para usar minha função if. Vai parecer mais conciso e melhor assim (eu acho):
Quando tento executar com o mesmo argumento acima, recebo o seguinte na minha máquina:
O que está acontecendo aqui?
Em Julia, e na maioria das linguagens de programação, quando chamamos uma função, os argumentos da função são avaliados antes que o corpo da função seja avaliado. Cada argumento para a função é avaliado exatamente uma vez.
Compare isso com uma ramificação if-then-else. Com esses ramos, apenas os ramos verdadeiros ou falsos são avaliados, de acordo com a lógica, mas não ambos.
A função fatorial_bad acima nunca retorna porque quando chamada myif_bad , todos os argumentos da função foram avaliados, incluindo as expressões true e false, resultando em chamadas recursivas fatorial_bad que nunca terminam . Para que isso funcione corretamente, apenas um ou outro pode ser avaliado, mas não ambos.
Então, como podemos fazer a função myif_bad funcionar com nosso fatorial_bad ?
Considere as seguintes revisões das funções myif e fatorial mostradas acima :
Espere um minuto... o que está acontecendo aqui? Como esse truque funciona?
Substituí argumentos para expressões verdadeiras e falsas por funções de zero argumentos em new myif_not_too_bad . Chamadas de função de argumento zero avaliam apenas o corpo quando são realmente chamadas. Como não há argumentos para essa função, apenas o argumento da expressão de condição é avaliado e é avaliado muito rapidamente.
Na nova função factorial_not_too_bad , criei expressões lambda que aceitam zero argumentos. Portanto, eles não serão executados até que a ramificação correta realmente chame essas expressões lambda. A ramificação if-then correta chama a expressão lambda e tudo é executado como pretendido:
Se você não deseja que algo seja executado imediatamente, seja porque não deseja avaliar todos os argumentos da função antes do corpo ou porque pode haver custos computacionais caros associados à execução disso o tempo todo, coloque-o em um zero -argumento expressão lambda e armazene-a — crie o encerramento correto e, em seguida, chame-a quando precisar dos resultados, não antes.
Medite sobre isso. Existem várias construções de programação funcional que dependem dos conceitos acima: avaliações preguiçosas, encerramentos, fluxos imutáveis e muitas outras ideias funcionais.





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)