sexta-feira, 11 de maio de 2007

Linguagens funcionais - parte 2





Vou viajar ao mundo dos betas .NET. Vale a pena porque as novidades parecem interessantes. Vou rumo ao desconhecido porque tenho pouca vivência com este outro mundo. Comentários corrigindo algo que não entendi direito serão muito bem vindos.

Siglas, quando acabo de aprender uma surge mais um monte. Algumas deixo de lado até que um dia fico curioso e procuro meu amigo google como fiz hoje. Queria saber o que é este tal de LINQ que a turma do .NET diz que é o futuro em termos de acesso de dados. Vou colocar aqui algumas coisas que aprendi navegando no google.

LINQ = Language INtegrated Query

É uma nova extensão para as próximas versões das linguagens da plataforma .NET também em sua próxima versão. Por enquanto só pode ser experimentada baixando versões beta do Visual Studio (orca) e da plataforma .NET. Foi concebida para simplificar consultas a dados na memória em coleções como arrays e listas, dados armazenados em bases de dados, dados em documentos XML, dados em arquivos ou em qualquer outra fonte de dados. Atende as questões de mapeamento O/R fazendo com que operações de consultas, tais como instruções SQL, façam parte da linguagem. O trocadilho do nome é para aparecer como o link que integra as consulta aos dados e as linguagens de propósito geral.

Algumas linguagens antigas como Clipper e FoxPro já tinham o acesso às bases de dados de forma embutida na linguagem. Esta facilidade acabou quando se passou a adotar o modelo cliente/servidor com as bases de dados acessadas via SQL. Pelo menos no que tange ao acesso às bases de dados, o futuro deixará a programação .NET de um jeito semelhante aos velhos Clipper e FoxPro. É claro que o LINQ vai muito mais além porque acessa diferentes fontes de dados usando os mesmos conceitos e é isto que é a novidade.

Em termos de inclusão na arquitetura .NET, o LINQ se posiciona como uma camada entre o programa e seus dados. As ferramentas do LINQ se integram na plataforma .NET como um conjunto de extensões onde cada uma tem um sabor para cada tipo de fonte de dados: LINQ para objetos, LINQ para SQL, LINQ para XML, etc.

Trata-se de mais um tentativa da Microsoft de minimizar o problema de descasamento de impedância entre as linguagens de programação e as bases de dados. Não é a sua primeira tentativa e este projeto também não é tão novo assim. Antes parecia que o caminho passaria pelo ObjectSpaces. Agora surge o LINQ oriundo do projeto Cω. Não será na primeira versão do LINQ que todos os problemas serão resolvidos como se pode ler no PDF LINQ 2.0: Democratizing the Cloud. Mas é sobre a versão 1.0 ainda a ser lançada que escrevo.

Vamos comparar um Alo Mundo bem simples atual e como será usando o LINQ. De cara alerto que o exemplo é simples demais mas acho que serve para mostrar o jeitão da coisa:
1. Alo Mundo Velho como é hoje:


using System;
static class AloMundoVelho {
static void Main() {
string[] words = { "Alo", "Maravilhoso",
"Mundo", "Velho",
"Microsoft" };
// Pega palavras ate 5 letras e imprime
foreach (string word in words) {
if (word.Length <= 5)
Console.WriteLine(word);
}
}
}



2. Alo Mundo Linq quando puder usar o LINQ:


using System;
using System.Linq;
static class AloMundo {
static void Main() {
string[] words = { "Alo", "Maravilhoso",
"Mundo", "Linq",
"Microsoft" };
// Pega palavras ate 5 letras
var shortWords =
from word in words
where word.Length <= 5
select word;
// Imprime
foreach (var word in shortWords)
Console.WriteLine(word);
}
}


Mostrei o uso do LINQ acessando um array na memória do mesmo jeito que faria se fosse uma base de dados ou um XML.Por ser muito simplório, o uso do LINQ só complicou e isto é o que normalmente acontece quando a gente adota um padrão genérico, como o bridge, por exemplo. Na medida em que as consultas se complicarem, as vantagens do LINQ prevalecerão.

O LINQ define um conjunto de operadores de consultas padronizados que permitirá filtrar, enumerar e criar projeções de vários tipos de collections usando a mesma sintaxe. Tais collections podem incluir arrays, classes enumeráveis, XML, datasets oriundos de bancos de dados e outras fontes de dados. Os operadores fornecem um meio uniforme de obter dados a partir de qualquer objeto que implemente a interface IEnumerable. É assim que arrays, collections, dados relacionais e XML são potenciais fontes de dados.
Abaixo mais um exemplo onde aparece o uso de uma expressão de consulta (query expression). Reparem na inicialização da variável local expr :


using System;
using System.Query;
using System.Collections.Generic;
class Gujeiros {
static void Main() {
string[] nomes = { "Paulo", "Philip",
"Fabio", "Carlos",
"Guilherme", "Daniel",
"Meyer", "Luca",
"Mauricio", "Louds",
"Rafael", "thingol"};
IEnumerable<string> expr =
from s in nomes
where s.Length == 5
orderby s
select s.ToUpper();
foreach (string item in expr)
Console.WriteLine(item);
}
}

Nenhum dos exemplos mostra, mas é preciso deixar claro que a solução não pretende esconder a base de dados como faz o Hibernate. E é claro também que o Java não tem nada parecido com isto.

Sem o LINQ, o atual programador .NET precisa conhecer e usar linguagens como SQL, XML ou XPath, várias tecnologias e APIs como ADO.NET ou System.Xml. Isto não será mais necessário com
os programas escritos em linguagens que incluem o LINQ. Para o programador menos avançado o LINQ pode ser considerado o que se chama de syntatic sugar, isto é, alguma coisa que se acrescenta sem afetar a funcionalidade e apenas torna mais "doce" o seu uso ou entendimento. Realmente seu uso diminuirá bastante a codificação.

O LINQ tem uma outra faceta que pode ser novidade para alguns programadores .NET: o mundo dele é strongly-typed. As vantagens imediatas do uso do LINQ é que as consultas serão verificadas em tempo de compilação e o programador ainda pode se beneficiar das sugestões do VisualStudio IntelliSense.

O LINQ se posiciona um passo acima da programação declarativa comum e é aqui que começo a escrever algo que tem a ver com o título deste blog. Como disse no meu texto anterior sobre linguagens funcionais, SQL é uma linguagem funcional. Só pela a inclusão do LINQ nas linguagens do .NET, já há um toque nelas de linguagem funcional. Porém, o LINQ usado com o C# 3.0, tem mais características de linguagem funcional porque o próprio C# 3.0 inclui novidades oriundas das linguagens funcionais.

Novidades do C# 3.0 (em cinza o que não é exatamente oriundo de linguagens funcionais):
  • Local Variable Type Inference - é o var que mostrei no exemplo Alo Mundo. Exemplos de var:
    • var i = 5; // equivalente a: int i = 5;
    • var s = "isto eh uma string"; // equivalente a: string s = "isto eh uma string";
  • Extension Methods (adiciona novas funções aos métodos existentes sem editar o fonte da classe)
  • Anonymous Types
  • Objects & Collections Initializers (dispensa múltiplos construtores)
  • Lambda Expressions
    É o cálculo lambda oriundo das linguagens funcionais e que existe no Lisp, Ruby e Phyton. Exemplo:

    Func incremento = i
    => i + 1;
    Incremento(5); // o resultado é 6
  • Expression Trees - representa Lambda Expressions como estrutura de dados
Mudanças como estas já motivaram algumas manifestações como:Final da história.

A Microsoft está incluindo facilidades das linguagens funcionais na sua plataforma. Aliás, ela pesquisa sua própria linguagem funcional baseada em coisas do Phyton, ML, OCaml, MATLAB, Scheme e do próprio C#. O site de pesquisa da F#
descreve o seguinte objetivo: Combining the efficiency, scripting, strong typing and productivity of ML with the stability, libraries, cross-language working and tools of .NET. E mais: F# is a programming language that provides the much sought-after combination of type safety, performance and scripting, with all the advantages of running on a high-quality, well-supported modern runtime system.

E a Sun? Bem, como disse antes as closures vem aí. Volta e meia alguém suspira por continuations. Já li que algumas sonhadas facilidades das linguagens funcionais seriam difíceis de incluir com segurança na JVM e continuations é uma delas.

Mas se o Java está limitado, se pode procurar outros caminhos. A possibilidade de rodar scripts na JVM e ainda usar dentro do código Java, oferece algumas perspectivas de estender o Java. Na linha de pesquisa deste blog, se alguém tiver know how, tempo e coragem, vale a pena experimentar alguns engines do scripting.dev.java.net. Lá tem engine para Haskell e Scheme com Jaskell e SISC respectivamente, Phyton com Jhyton, Ruby com JRuby e o Groovy.

Conclusão e recomendação:
Como disse no outro post, mudanças estão acontecendo e algumas novidades vem justamente das linguagens funcionais. Conhecer um pouco de uma delas não toma tanto tempo assim e pode ter a sua utilidade mesmo que não seja você um Neal Gafter, Doug Lea ou um Gilad Bracha. No mínimo você estará preparado para entender o que vem por aí.

Duas alternativas de linguagens funcionais que me atraem são erlang e Scala. Ambas tem seu valor e são adequadas para processos concorrentes. Escolhi começar pelo erlang que é uma linguagem funcional do tipo do Haskel e é orientada para concorrência. Parece muito adequada para o hardware de hoje em que os processadores estão crescendo mais rapidamente de tamanho do que na capacidade de processamento. O aumento de tamanho é porque as CPUs agora tem mais núcleos sendo já comuns os processadores dual core e quad core. Em breve isto irá longe e haja software para explorar. Estou apostando no erlang com a crença de que com ele será mais fácil encarar o desafio de usar corretamente estas facilidades de hardware. Espero que o erlang me dê também as noções mínimas de programação funcional que acho necessárias para seguir entendendo as mudanças no mundo do desenvolvimento de sistemas.
}

6 comentários:

Anônimo disse...

Não tinha lido nada sobre LINQ e "a primeira vista" achei bacana. Belo post!

Unknown disse...

Oi Luca. Primeiro queria dar parabéns por finalmente começar a bloggar :). Agora estou me sentindo culpado que meu blog está às moscas.

Eu gostei do artigo, a tecnologia do LINQ é bem promissora, apesar do mal de origem. Eu não sei bem como as expressões LINQ se encaixariam no meio de um modelo de domínio OO tradicional; imagino que ainda seja necessário alguns anos de experiência para que se desenvolvam boas práticas.

Tenho a impressão que o primeiro item da lista de funcionalidades do C# é sim oriundo da programação funcional; acho que Inferência de tipo vem de ML. E a relação entre lambda-expressions e cálculo lambda não é muito direta (acho que Guy Steele cunhou o nome quando estava fazendo Scheme, chamando os Procedure Values de Lambda Expressions para enfatizar o escopo léxico).

Eu ando brincando bastante com Scala e uma novidade que vai aparecer logo é a adição de Structural Subtyping, estilo Anonymous Types do C#, permitindo fazer coisas parecidas com o LINQ. Ainda não tem Expression Trees, mas dá para simular como uma espécie de DSL; a biblioteca de acesso a BD em scala já faz algo assim hoje.

Último comentário: não sei se Erlang é tão parecido com Haskell assim, já que é dinâmicamente tipado e usa avaliação estrita (o Haskell é *bem* estáticamente tipado e tem lazy evaluation).

Abraços e estou aguardando os próximos posts.

Luca Bastos disse...

Rafael

Obrigado pelas observações.

Na verdade este post foi como uma espécie da notas de aula escritas ainda sem conhecer muito bem sobre o que estava escrevendo. Daí esperava mesmo que alguém me corrigisse em algumas coisas.

Li em algum lugar sobre a semelhança entre o Haskell, sobre o qual nada sei, e o erlang que estou apenas entrando no capítulo 3 do livro. Repeti pois acreditei no que li sem muitas condições de saber se era verdade ou não.

Unknown disse...

Bom, como eu disse no GUJ, tenho medo de Haskell :)

Luca Bastos disse...

Rafael

Alterei a cor do texto no que concerne a inferência de tipo pois realmente vem das LFs. Obrigado.

Ednelson disse...

Luca, acabei de ler esta notícia na InfoQ que me remeteu imediatamente a este post seu. A notícia trata de Quaere, uma iniciativa da comunidade que emula funcionalidades do LinQ em Java. Que somprem os ventos da mudaça e que Darwin vença :)

http://www.infoq.com/news/2007/09/quaere-linq

Quem sou eu

São Paulo/Paraty, SP/RJ, Brazil
Engenheiro estrutural COPPE/UFRJ por formação, desenvolvedor Java por experiência e poeta se sobrasse tempo