Groovy 1.8 :: LINQ применяется - PullRequest
8 голосов
/ 06 июня 2011

ОБНОВЛЕНИЕ 8/31/2011
Гийом Лафорж почти сделал это:
http://gaelyk.appspot.com/tutorial/app-engine-shortcuts#query

Похоже, он выполняет преобразование AST, чтобы выполнить:

alias as Entity

немного. Классная штука, Groovy 1.8 + AST transform = LINQ-esque запросы на JVM. Решение GL требует больше работы, насколько я вижу, чтобы реализовать все возможности запросов (например, подзапросы, объединение с использованием (полевого) синтаксиса и т. П.), Но для его проекта Gaelyk, по-видимому, нет необходимости.

EDIT

В качестве обходного пути к достижению чистого синтаксиса LINQ я решил определить псевдонимы. Ничего страшного, и устраняет серьезные препятствия, которые, вероятно, потребуют сложных преобразований AST, чтобы осуществить.

Итак, вместо:

from   c as Composite
join   t as Teams
...

Теперь я определяю псевдонимы (примечание: необходимо привести к автоматическому заполнению полей):

def(Teams t,Composite c,Schools s) = [Teams.new(),Composite.new(),Schools.new()]

и использовать синтаксис карты для from, join и т. Д.

from    c:Composite
join    t:Teams
...

Чтобы решить проблему № 2 (см. Оригинал ниже), добавьте методы уровня экземпляра getProperty к каждому псевдониму pogo (область действия которого ограничена закрытием ORM, в котором он вызывается, nice). Мы просто возвращаем имя свойства строки при создании оператора sql.

[t,c,s].each{Object o-> o.metaClass.getProperty = { String k-> k } }

Добиться "хорошего" прогресса; -)

Теперь, чтобы выяснить, что делать с "=", это сложно, так как заданное свойство void. Возможно, придется использовать eq, neq, gt и т. Д., Но на самом деле предпочтительнее литеральные символы, что делает читаемость ближе к sql.

Если интересно, LINQ делает немного закулисного. У Джона Скита (хвала его имени) есть хороший ТАК ответ Как внутренне работает LINQ?

ORIGINAL

Проверял LINQ, очень впечатлен.

// LINQ example
var games =
    from t in Teams
    from g in t.Games
    where g.gameID = 212
    select new { g.gameDate,g.gameTime };


// Seeking Groovy Nirvana
latest { Integer teamID->
    from   c as Composite
    join   t as Teams
    join   s as Schools on ( schoolID = {
                     from   Teams
                     where  t.schoolID = s.schoolID } )

    where   t.teamID = "$teamID"
    select  c.location, c.gameType, s.schoolName
    group   c.gameID
    order   c.gameDate, c.gameTime
}

Предлагаемая версия Groovy компилируется нормально, и если я определяю псевдонимы c, t, s с соответствующими им POGO, я получаю строго типизированный IDE auocomplete на полях, хорошо. Однако нигде рядом с LINQ, где нет (видимых) определений переменных, кроме самого запроса, полностью самодостаточного и строго типизированного, вау.

Хорошо, так можно ли это сделать в Groovy? Я думаю (надеюсь), да, но я одержим 2 вопроса:

1) Как неявно заполнить переменную псевдонима без определения? В настоящее время я переопределяю asType () для String, поэтому в "from c as Composite" c получает приведение к Composite. Отлично, но IDE "думает", что в области закрытия неопределенный c является строкой и, таким образом, не выполняет автозаполнение полей POGO; - (

2) Поскольку # 1 не решен, я определяю псевдонимы, как указано выше, чтобы я мог получить автозаполнение. Отлично, взломан (по сравнению с LINQ), но делает свое дело. Проблема здесь в том, что в «select c.location, c.gameType ...» я бы хотел, чтобы поля не оценивались, а просто возвращали «c.location» в метод выбора ORM, а не ноль (который является его значение по умолчанию). getProperty () должен работать здесь, но мне нужно, чтобы он применялся только к полям pogo при вызове из области ORM (например, методы, специфичные для поля orm, такие как select, order, group и т. д.). Потерянный бит там, возможно, есть способ аннотировать методы orm, или только вызывать «специальный» pogo getProperty через вызовы методов orm (который является делегатом замыкания в запросе выше нирваны).

Следует отметить, что я не собираюсь создавать всеобъемлющий LINQ для Groovy, но я бы хотел, чтобы это было одно конкретное подмножество LINQ.

1 Ответ

0 голосов
/ 05 октября 2011

Одна из главных причин, по которой Гийом использует преобразование AST, связана с проблемой "=". Даже если вы используете == для сравнения, как это обычно делается в Groovy, из вызванного для него метода CompareTo вы не сможете различить ==,! =, <=,> =, <,>. Есть два возможных пути для этого в более поздних версиях Groovy, которые обсуждаются. Один из них заключается в использовании для каждого из них различных методов сравнения, другой - для хранения минимального AST, к которому вы можете обращаться во время выполнения. Это идет в направлении C # и является довольно мощным инструментом. Проблема больше в том, как сделать это эффективно.

...