Сколько стоит LINQ? - PullRequest
       16

Сколько стоит LINQ?

10 голосов
/ 13 сентября 2009

Я смотрю на LINQ, и язык запросов (по крайней мере, на первый взгляд) представляет собой не что иное, как реализацию пониманий карт и / или списков, как в Haskell и других языках FP (в частности, обобщение 'map) 'и' для 'в Scala). Это правильно? Есть ли что-то еще в синтаксисе, чем этот? Из бездыханного тона книги, которую я читаю («Essential LINQ»), может показаться, что здесь что-то новое или инновационное.

Для реализации LINQ есть целые бэкэнд, конвейер, деревья выражений первого порядка, типы и т. Д., Но мой вопрос касается самого языка запросов.

Приветствия

Джо

Ответы [ 5 ]

25 голосов
/ 13 сентября 2009

Функционально говоря, LINQ - не что иное, как синтаксическое упрощение выражения монад. Linq to Objects (списки-понимания - даже это уже было бы чрезвычайно полезно), о которых вы говорили, это всего лишь одно возможное применение этого (аналогично List-Monad в Haskell).

Если вы напишите

from x in expr1
from y in expr2
select x + y

это не что иное, как

do
    x <- expr1
    y <- expr2
    return $ x + y

в Хаскеле.

Конкретное действие зависит от определенных пользователем Linq-провайдеров (Extension-Methods), из которых Linq.Enumerable является лишь одной реализацией, включающей IEnumerable s.

Предоставляя его, вы можете создать совершенно новую семантику LINQ для ваших типов.

Пример: учитывая тип Option для вычислений, которые могут завершиться ошибкой (значения, допускающие значение NULL), можно определить провайдера Linq для запроса к ним.

public static class MaybeExtensions
{
public static Option<T> ToMaybe<T>(this T value)
{
    return Option<T>.Some(value);
}

public static Option<U> SelectMany<T, U>(
    this Option<T> m, 
    Func<T, Option<U>> k)
{
    return !m.IsNone ? Option<U>.None : k(m.Value);
}

public static Option<V> SelectMany<T, U, V>(
    this Option<T> m, 
    Func<T, Option<U>> k, 
    Func<T, U, V> s)
{
    return m.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe()));
}
} 

Теперь это позволило бы нам написать такой код:

var sum = from x in ReadNumber("x")
          from y in ReadNumber("y")
          select x + y; 

Вычисление вернет значение только в случае успешного выполнения всех вычислений и в противном случае произойдет сбой первого неудачного вычисления.

В сочетании с деревьями выражений Linq может быть чрезвычайно мощным и позволяет вам выражать -

  1. Доступ к базе данных
  2. Асинхронный поток программ
  3. Может быть, Монады
  4. Список понятий
  5. парсеры рекурсивного спуска
  6. Продолжения
  7. Мини-языки
  8. Параллельные вычисления (PLinq)

Некоторые ссылки:

В сочетании с комбинаторами с фиксированной точкой Linq предоставляет полный функциональный мини-язык ( Linq raytracer ).

Обратите внимание, что Scala и F # оба имеют сходные понятия в выражениях для вычислений и вычислениях, оба являются монадическими абстракциями:

Scala:

for (x <- expr1
     y <- expr2) yield x + y

F #:

monad {
    let! x = expr1
    let! y = expr2
    return x + y
}
5 голосов
/ 13 сентября 2009

Дыхание, вероятно, предназначено для всего этого "очевидного" материала, некоторые из которых (например, деревья выражения) действительно превосходны. Язык - это всего лишь средство доступа; Вы взволнованы по поводу ключевого слова throw или функциональности, которую оно предоставляет?

4 голосов
/ 13 сентября 2009

Помимо чтения книги об этом, вы уже использовали LINQ? Я нашел, что это было огромной экономией времени в моей ежедневной работе по программированию. Для меня это следующий шаг абстракции, который можно использовать для объединения различных источников данных, таких как XML или SQL, и работы с ними на одном и том же «языке».

Кроме того, я рекомендую это интервью с Андерсом Хейлсбергом о функциональном программировании и LINQ.

3 голосов
/ 13 сентября 2009

Ядро LINQ, синтаксис запроса, на самом деле не огромен по объему. Это просто некоторые очень буквальные переводы для методов и лямбд - так что

var qry = from x in src
          where x.Foo == "foo"
          select x.Bar;

это буквально :

var qry = src.Where(x => x.Foo == "foo").Select(x => x.Bar);

Он ничего не знает о методах расширения (хотя они являются наиболее распространенной (но не только ) реализацией), и ничего о Expression и т. Д. Количество ключевых слов (и, следовательно, количество требуемых методов). реализации) не огромен. Джон однажды попытался реализовать их все за 1 час (в режиме реального времени). Он не так уж плохо; -p


Возможно, наиболее впечатляющей частью LINQ является поддержка дерева выражений , необходимая для использования LINQ с базами данных - то есть лямбда-выражение, которое можно скомпилировать или в делегировать или объектной модели, которая представляет написанный код. Интересно, что эта же идея прослеживается в том, как работает разрешение DLR в 4.0.

2 голосов
/ 13 сентября 2009

LINQ был вдохновлен HaskellDB, как неоднократно заявлял Эрик Мейер , например. в Признания продавца подержанного языка программирования (Рассказ о массе на Haskell) , так что это само по себе не является новой концепцией. Использование одного и того же языка для запросов к различным источникам является в некоторой степени новаторским, хотя тот факт, что вложенная реляционная модель охватывает XML, объекты и реляционные базы данных, был продемонстрирован исследователями ранее. Для меня очень здорово то, что он встроен в популярный, универсальный и в первую очередь объектно-ориентированный язык, чего раньше не было.

Scala IMHO обладает способностью включать что-то подобное. Пока что для Scala у нас есть Stefan Zeiger ScalaQuery и Daniel Spiewak ScalaQL , которые следуют по стопам LINQ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...