Linq (.net)

15 respostas
T

Tanto falaram sobre Closures em Java, mas não mencionaram nada sobre implementar algo semelhante a LINQ (.NET) no Java.

Andei usando um pouco, e embora seja um pouco mais lento que o programa equivalente usando “for” ou “foreach”, é bem mais claro - e você sabe, quando um programa é mais claro, tende a ficar mais fácil de otimizar porque se usam os algoritmos corretos, não os mais fáceis de implementar.
(É um pouco mais lento, porque internamente usa iteradores que usam “continuations”, que em C# se chama “yield”). “Continuations” é outra coisa que gostaria de ver no Java.

Um exemplo que dei há pouco tempo atrás aqui no fórum (agrupar uma lista de objetos por um determinado campo, e totalizar os valores, usando uma sintaxe semelhante ao SQL) me fez ver que seria muito importante ter algo semelhante no Java.

15 Respostas

L

Uma coisa: se houvesse Closures em Java, não acha que seria fácil implementar uma biblioteca “LINQ-like”, sem necessidade de uma bênção do JCP?

Aliás, dando uma fuçada no Google, descobri um post que fala sobre uma implementação do LINQ em Java http://andersnoras.com/blogs/anoras/archive/2007/09/11/introducing-quaere-language-integrated-queryies-for-java.aspx

A biblioteca tenta dar um chapéu no compilador declarando muita coisa como String, o que é péssimo. Mas numa implementação baseada em Closures, acho que o negócio fica melhor, não acha não?

T

O recurso de Closures é necessário mas não é suficiente para implementar o LINQ.

Uma das idéias do LINQ é que as bibliotecas possam ter acesso à árvore sintática abstrata do próprio programa.
Dessa forma, em vez de você ter um encadeamento de funções (que é o que você aparenta ver em um programa em C# usando LINQ com a notação funcional), você passe as próprias funções e “closures” para serem analisadas pela biblioteca, para que ela gere código.

Um exemplo que dou é o LINQ para SQL: a biblioteca (não o compilador!) converte o seu código (incluindo o que você passaria como “closures”) para uma instrução SQL equivalente (se isso for possível), e manda essa instrução.

M

Thingol, você tem noção se é fácil ou difícil de se fazer isso pra Java?

Tem alguma chance de se pegar o AST do bytecode em tempo de execução de forma simples?

Quem faz uma coisa parecida é o DB4O com as suas queries. Segundo eles, eles pegam o seu código (escrito em Java ou C# puro) e transformam numa consulta analizando o que você colocou lá.

L

Olá

Googlando achei algo parecido http://josql.sourceforge.net/

Achei também: http://andersnoras.com/blogs/anoras/archive/2007/09/18/what-s-the-difference-between-josql-quaere.aspx

Meu primeiro contato com o LINQ não passou de um breve vôo rasante. Mas me impressionou tanto que até bloguei obre ele: http://lucabastos.blogspot.com/2007/05/linguagens-funcionais-parte-2-vamos.html
O comentário do Ednelson me chamou a atenção sobre o quaere. Mas este projeto parece parado e sem futuro.

[]s
Luca

T

AST por definição é do código-fonte, não do bytecode. Você vê que isso tem de ter algum suporte da linguagem, para obter isso sem ter de usar uma ferramenta adicional.
No caso do Java é possível fazer algumas coisas, veja isto aqui: Source Code Analysis Using Java 6 APIs

L

Existe um monte de coisas que existem para suportar LINQ que seria muito, mas muito difícil implementar em Java.
Primeiro que todos os métodos envolvidos em um statement LINQ são resolvidos via extension methods, oque torna possível usar LINQ
sobre qualquer objeto/fonte de dados desde que seja possível resolver um método que faça a conversão apropriada para IEnumerable.

Fora que é possível ir incrementalmente aumentando o suporte a LINQ para sua fonte de dados, sabendo que sempre existirá o linq-to-objects
como resguarda para garantir que seja possível fazer qualquer tipo de query sobre.

Expression trees permitem, por exemplo, um framework de ORM não ter uma API de criteria e ao mesmo tempo suportá-las de maneira muito mais sucinta.

T

“Extension Methods” - para quem não sabe o que é isso:
É algo muito simples, mas muito poderoso. À primeira vista, é só um “syntatic sugar” - lembram-se daquelas bibliotecas de manipulação de strings que volta e meia sempre criamos, por exemplo:

class UtilString {
...
    public static boolean isNumeric (String str) {
        ...

Você fica se perguntando se a própria classe String não deveria ter um método isNumeric, para que você pudesse fazer algo como:

import static UtilString;

String s = "Um Dois Três da Oliveira Quatro";
if (s.isNumeric()) ...

em vez de

import UtilString;

String s = "Um Dois Três da Oliveira Quatro";
if (UtilString.isNumeric (s))...

que é meio desajeitado. Em C#, basta você fazer este tipo de declaração (estou simplificando um pouco):

public static bool IsNumeric (this string str) {
        ...

para que você possa usar a sintaxe

string s = "Um Dois Três da Oliveira Quatro";
if (s.IsNumeric()) ...
L

Extension methods são muito úteis pois o compilador faz match polimórfico deles e funcionam em tipos escalares também (int por exemplo).

É muito fácil escrever fluent APIs e mini DSLs com extension methods:

int x = 10.percent.of(20); //2

class Percentage {
    int value;

    public static percent(this int val) { return new Percentage (val); }
    public int of (int v) { return v * value / 100; }
}

A vantagem do matching ser polimórfico é que rola fazer o seguinte:

static class Extensions {
        public static void EachWithIndex<T> (this IEnumerable<T>[] array, Action <T, int> closuse) {
                for (int i = 0; i < array.Length; ++i)
                        closuse (array [i], i);
        }
}

var x = new int[] {1,2,3,4,5};
x.EachWithIndex ( (val, idx) => Console.WriteLine ("arr[{0}] = {1}", idx, val));
A

Vale a pena aprender LINQ?
Pergunto isso porque vai ter um curso aqui na Universidade onde estudo e posso escolher só 2 mini-cursos. Um deles é Controle de Versões. Outro estava em dúvida entre Qualidade de Serviço (QoS) e LINQ. Ainda não me decidi :frowning:

T

Acho que LINQ você vai ter de apanhar um pouco sozinho para aprender direito. Vá assistir ao curso de QoS.

Use o seguinte programa para treinar o uso de LINQ:

LINQpad

S

Ainda bem. Para a versão 7 fala-se de uma sintaxe especial para tratamento de xml.
Este tipo de linguagens não OO sendo incluidas dentro de uma linguagem OO além de consporcar a sintaxe e lista de palavras reservadas nos retorna ao tempo da POS (programação orientada a strings).

É muito mais , digamos … moderno , simplesmente implementar QueryObjets genericos em Java ( os famosos Criteria ) que possam ser usados em JPA ou contra uma Collection.

SQL tem que morrer para o mundo OO. Temos que continuar programando cada vez mais com objetos e cada vez menos com linguagens/estruturas alternativas como XML, SQL e afins …

T

Eu em particular discordo disso. Acho que programação orientada a objetos não resolve TODOS os problemas*; cada problema tem a maneira mais adequada de resolver, e muitos dos problemas requerem outros paradigmas (programação funcional, declarativa à la SQL, etc.).
As linguagens que estão na moda (Ruby, Scala etc.) não têm esse “purismo” de orientação a objetos - se pensar bem, nem o Java é puramente orientado a objetos, muito pelo contrário. Se o Java tem de se modernizar, é necessário suportar também outros paradigmas - como a programação genérica que mal e mal foi implementada com o tal de “Generics” e a programação declarativa que mal e mal foi implementada com “Annotations”.

  • Na verdade acho que o radicalismo acaba é criando novos problemas, em vez de resolvê-los.
S

thingol:
Eu em particular discordo disso. Acho que programação orientada a objetos não resolve TODOS os problemas*; cada problema tem a maneira mais adequada de resolver, e muitos dos problemas requerem outros paradigmas (programação funcional, declarativa à la SQL, etc.).
As linguagens que estão na moda (Ruby, Scala etc.) não têm esse “purismo” de orientação a objetos - se pensar bem, nem o Java é puramente orientado a objetos, muito pelo contrário. Se o Java tem de se modernizar, é necessário suportar também outros paradigmas - como a programação genérica que mal e mal foi implementada com o tal de “Generics” e a programação declarativa que mal e mal foi implementada com “Annotations”.

Foi implementada sem fugir da OO.
Uma das razões para a criação da API de script para java foi exactamente essa : se java não suporta, faça noutra linguagem.
A ideia sempre foi não jogar tudo no java e transformá-lo em um frankenstein como o C++ ou C# são. Cada linguagem tem o seu nicho e vc quer usar outro paradigma, usa outra linguagem.

Exactamente porque os paradigams do Java não são compativeis com alguns outros que novas linguagens estão sendo portadas para a JVM. Quer dinamismo e programação orientada a metadados use Ruby ou JavaScript ou Groovy. Quer escrever programa com base cientifica ? use Fortress , quer acessar o hardware em baixo nivel ou rincar com a memoria não gerenciada use C++ ou C# unsafe. Afinal a propria JVM é construida com C++.

Não é uma questão de purismo. É uma questão de conceito e compromisso. Java ainda não fugiu do seu conceito e compromisso de ser OO. E mesmo assim tem um monte de funcionalidade. Na hora que o Java violar isso é a prova que a Sun se vendeu, tal como a Microsoft que se vendeu ao criar um C# onde vc pode usar memoria não gerenciada, o que viola todos as certezas basicas do resto da linguagem.

A

thingol:
Acho que LINQ você vai ter de apanhar um pouco sozinho para aprender direito. Vá assistir ao curso de QoS.

Use o seguinte programa para treinar o uso de LINQ:

LINQpad

Beleza cara, valeu!

L

Ainda bem. Para a versão 7 fala-se de uma sintaxe especial para tratamento de xml.
Este tipo de linguagens não OO sendo incluidas dentro de uma linguagem OO além de consporcar a sintaxe e lista de palavras reservadas nos retorna ao tempo da POS (programação orientada a strings).

É muito mais , digamos … moderno , simplesmente implementar QueryObjets genericos em Java ( os famosos Criteria ) que possam ser usados em JPA ou contra uma Collection.

SQL tem que morrer para o mundo OO. Temos que continuar programando cada vez mais com objetos e cada vez menos com linguagens/estruturas alternativas como XML, SQL e afins …

Tem uma série de coisas que você falou que simplesmente não são verdade.

LINQ foi construído para permitir consultas e sobre objetos ou qualquer outra fonte de dados. O mapeamento para XML ou SQL é uma virtude do recurso e não é o ponto central.
Tem gente construindo coisas como processamento paralelo, via o PLINQ, a computação distribuída, via DryadLINQ. SQL é um dos muito e muitos mapeamentos.

LINQ não usar strings, são todos elementos da linguagem e typesafe. Sua afirmação nesse sentido não poderia estar mais equivocada, pois uma API de criteria usa strings aos montes.

Criteria q = new Criteria(Box.class);
q.isEquals("size", 90);
var q = from b inBox.Extent where b.Size == 90

Vamos lá, conte o número de strings em cada um :wink:

O código LINQ é convertido em uma AST typesafe para ser usado em runtime.

Criado 23 de maio de 2008
Ultima resposta 29 de mai. de 2008
Respostas 15
Participantes 7