Extension Methods, métodos e tipos anônimos, lambda expressions, dentre outras tecnologias permitem que escrevamos códigos menores, mais declarativos e mais assertivos.
LINQ é expressão de todas essas melhorias, mas, ao meu ver, é apenas um demonstrativo das melhorias que podemos fazer em nossos códigos.
É certo que linguagens mais novas – como F#, IronPython ou IronRuby – tem uma sintaxe mais fácil e direta para abordagem funcional. Mas, de forma alguma, não podemos dizer que estamos mal servidos usando C#.
Nesse post, pretendo explorar algumas “coisinhas” interessantes que conseguimos fazer em C#. Aplicações práticas do paradigma de programação funcional no dia-a-dia de nossos códigos.
Lambda Expressions como dado
Em algumas circunstâncias, podemos usar a sintaxe Lambda para representar uma expressão que desejamos manipular como dado no lugar do resultado da expressão em si. Veja o trecho de código, extraído dos testes do EasyMock, que segue:
Observe as linhas 2, 5 e 8. Na prática, as chamadas para o método Process nunca serão realizadas. Por “baixo do capô”, o framework analisa a expressão para criar o mapeamento necessário. O mesmo ocorre, por exemplo, com o método Map do NHibernate. No caso do EasyMock, essa técnica garante que todos os métodos sejam validados em tempo de compilação e que todo o código seja editado com apoio do IntelliSense.
Suporte a passagem de blocos de código como parâmetro
Uma das melhores características da programação funcional está relacionado ao conceito de Higher Order Functions. Como bem apresentado por Joel Spolsky no provocativo “Can Your Programming Language Do This?”, podemos reduzir a duplicação de código utilizando algum mecanismo de composição.
É comum encontrarmos longas sequências de código quase idênticas onde a “diferença” está em umas poucas linhas de código. Uma das maneiras de se evitar esse problema no mundo orientado a objetos é fazer herança usando um template method. Entretanto, cada vez mais, eu penso que passar o “bloco de código recheio” como parâmetro seja uma abordagem superior.
Além disso, podemos “enxugar” o código significativamente. Repare essa construção simples:
Pode ser escrito assim:
Delayed Execution
Outra “capacidade” muito importante para programação funcional é a capacidade de agendar a execução de um código. Ou seja, permitir que um código seja executado em um momento diferente ao que aparece no programa. Segue outro trecho de código extraído do EasyMock que apresenta esse conceito:
Os trechos de código em passados como parâmetro em Callback não são executados nesse instante.
Memoization
Nome complicadinho, não acha? Trata-se de uma técnica usada para evitar execução de chamadas “pesadas” reutilizando o resultado de execuções prévias. Um bom exemplo da técnica pode ser encontrado em Fibonacci Numbers, Caching and Closures de Dustin Campbell. Aqui uma transposição da implementação que ele apresentou sem uso da técnica:
Implementando memória …
Que diferença? Bem, sem memória, alguns minutos. Com memória, instantâneo.
Map/Reduce Pattern
Para quem gosta de Python (e outras que suportam esse padrão), LINQ trouxe uma ótima novidade. Map = Select e Reduce = Aggregate. Um exemplo simples. Somar todos os numeros de uma lista:
Observe que o Extension Method Sum é uma especialização de Aggregate. Outro aspecto importante é que podemos, usando o método Select, adicionar filtros rapidamente a consulta.
Bem, por hoje, é isso
agosto 27th, 2010 → 2:41
[...] eu nunca havia realmente entendido o conceito. Minha inspiração e busca pela técnica veio deste post do Elemar [...]
setembro 20th, 2010 → 0:39
[...] Functional Programming – Outras considerações [...]
novembro 17th, 2011 → 23:46
[...] algum tempo, escrevi um post falando sobre técnicas de Functional Programming em C#. Dentre essas técnicas, está Memoization. Basicamente, essa técnica melhora a performance de [...]