Arquivo da categoria ‘Linguagens funcionais’

Linguagens funcionais - parte 2

Sábado, Maio 12, 2007


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.

}

Linguagens funcionais

Sexta-Feira, Maio 11, 2007


Há alguns dias atrás coloquei a seguinte pergunta no GUJ:

Sei que muitas faculdades lá fora ensinam linguagens funcionais de programação e fiquei curioso de fazer uma pequena enquete no GUJ. Perguntei:

  1. Você já ouviu falar ou já usou alguma linguagem funcional?
  2. Você aprendeu alguma linguagem funcional? Qual? Foi na faculdade? Qual faculdade?
  3. Se aprendeu alguma linguagem funcional, você acredita que conhecer uma linguagem funcional pode lhe dar alguma vantagem no futuro?
  4. Se aprendeu alguma linguagem funcional, você admite que no futuro haverá espaço para programadores em linguagens como erlang, links, scala ou outra qualquer do gênero?

Vale a pena ler as respostas uma a uma. Colocarei aqui minha impressão sobre esta pesquisa. No fim revelarei parte dos motivos que me levaram a fazê-la. Em outro post, abordarei um tema que deixará claro porque acho que há motivos imediatos para que a gente procure saber mais sobre linguagens funcionais.

Mas antes de falar sobre as respostas listarei algumas definições encontradas com ajuda do google:

Java, C, Pascal, etc. são o que se chamam de linguagens imperativas no sentido em que consistem em uma seqüência de comandos. Mas o que caracteriza uma linguagem funcional?

Segundo a introdução ao Haskell, um programa funcional é uma expressão e é executado avaliando a expressão. O texto lembra que quem usou uma planilha já tem experiência com programação funcional. Nas planilhas se especifica o valor de uma célula em função dos valores de outras. O foco está no que é calculado e não no como é calculado. Outro exemplo citado é o da linguagem de consultas SQL onde se escreve a expressão sem se preocupar como ela será implementada pelo sistema gerenciador de base de dados.

Segundo http://www.nist.gov/dads/HTML/purelyfnctnl.html, linguagem funcional não permite nenhuma ação destrutiva do tipo sobrescrever dados. As linguagens puramente funcionais são livres de “side effects”, isto é, a chamada de uma função não tem nenhum efeito além de avaliar o resultado da função.

Segundo http://cbbrowne.com/info/functional.html, programação funcional é um estilo de programar que enfatiza a avaliação de expressões ao invés da execução de comandos. As espressões nestas linguagens são formadas usando funções para combinar valores básicos. Uma linguagem funcional é uma linguagem que suporta e encoraja a programação no estilo funcional.

Acho que estas definições ainda não deixaram as coisas 100% claras mas o google está aí para resolver esta lacuna. Chega de definições e vamos aos finalmentes.

Não sei se o número de respostas permite tirar muitas conclusões porque apesar do tópico ter sido lido por quase 600 gujeiros, só 17 responderam.

O que consegui entender das respostas foi:

  • Algumas faculdades ensinam algum tipo de linguagem funcional;
  • Alguns desenvolvedores mais interessados já estudaram alguma linguagem funcional, mas não ficou claro com qual profundidade;
  • Foi citado que a exposição a uma linguagem funcional torna mais fácil entender algumas novidades pois elas muitas vezes são oriundas de alguma linguagem funcional;
  • A maioria não acredita que vá usar alguma linguagem funcional em sua vida profissional

O que eu posso dizer sem antecipar o assunto do meu próximo post?

Muitos esqueceram que já usam linguagens funcionais nas consultas SQL, nas planilhas, nas transformações XSLT e em muitas outras áreas. Ninguém se lembrou de que o conceito de generics do Java veio de uma extensão do Java chamada GJ. Esta é baseada em outra extensão do Java chamada pizza, que por sua vez incorpora princípios de linguagens funcionais e closures é um deles. Ah, acho que quase todo mundo no GUJ já ouviu falar em closures que é, mais um conceito do mundo das linguagens funcionais e que a gente vai usar com o Java 7.

E porque fiz esta pesquisa com nossos homens de Java?

  • Porque neste modelo de programação, há muita pesquisa acadêmica que repercurte também em grandes empresas como a Microsoft, por exemplo. Devido a isto, há alguns indícios que estamos em meio a uma revolução no modo de escrever programas, com as linguagens pouco a pouco incorporando as facilidades das linguagens funcionais.
  • Porque no Java serão incluídos alguns conceitos oriundos das linguagens funcionais já no Java 7 e possivelmente alguns outros nas versões subseqüentes. Apesar de que, no Java esta evolução será mais lenta do que nas linguagens dominadas pela Microsoft. O motivo do Java evoluir mais devagar é porque em casa que todo mundo manda ninguém tem razão. A vantagem da padronização feita em grupo do tipo JCP vira transtorno no momento de decidir rápido por mudanças mais radicais que o mercado pode exigir.
  • Para entender conceitos novos como closures e continuations.
  • Para estar apto a executar tarefas específicas programando em outras linguagens com mais facilidades de conviver com máquinas multiprocessadas como Scala ou erlang.

Há outros motivos. A motivação mais forte e imediata para aprender pelo menos um mínimo de linguagens funcionais, será assunto do meu próximo post quando falarei um pouco de .NET.