2009-09-13 10 views
10

Zajmuję się LINQ i pojawia się język zapytań (przynajmniej na powierzchni), który jest niczym więcej jak implementacją map i/lub list zrozumień w języku Haskell i innych językach FP (szczególnie uogólnienie "map" i "dla" w Scali). Czy to jest poprawne? Czy jest więcej do składni niż to? Z bezdusznego tonu książki, którą czytam ("Essential LINQ") wydaje się, że jest tu coś nowego lub innowacyjnego.Ile kosztuje LINQ?

Istnieje cały back-end, potok, drzewa i typy ekspresji pierwszego rzędu, aby zaimplementować LINQ, ale moje pytanie dotyczy samego języka zapytań.

Cheers

Joe

Odpowiedz

25

Funkcjonalnie używany, LINQ to nic innego jak syntaktyczne uproszczenie wyrażania monad. Linq to Objects (Zrozumienie list - nawet to byłoby już bardzo użyteczne), o którym mówiłeś, to tylko jedna z możliwych aplikacji tego typu (podobna do List-Monad w Haskell).

Jeśli piszesz

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

to nic ale

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

w Haskell.

Beton rzeczą, która odbywa się w zależności od zdefiniowanych przez użytkownika LINQ dostawców (przesuwnych metody), z których tylko jedna jest Linq.Enumerable realizacja udziałem IEnumerable s.

Dzięki temu można stworzyć zupełnie nową semantykę LINQ dla swoich typów.

Przykład: Biorąc pod uwagę typ, który może się nie powieść (wartości zerowalne), można zdefiniować dostawcę Linq do przeszukiwania nad nim.

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())); 
} 
} 

To teraz pozwalają nam napisać taki kod:

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

Obliczenia będą tylko zwrócić wartość jeżeli wszystkie obliczenia udało i nie inaczej będzie w pierwszym przypadku braku jednego.

W połączeniu z drzewami ekspresyjnych LINQ może być bardzo mocny i pozwala wyrazić -

  1. Database dostęp
  2. Asynchronous przepływu programowe
  3. Maybe-monad
  4. listowe Lista
  5. rekurencyjne Descent Parsery
  6. Kontynuacje
  7. Mini języki
  8. obliczenia równoległe (PLinq)

kilka linków:

W połączeniu z kombinatorami stałoprzecinkowymi, Linq oferuje kompletny funkcjonalny mini-język (Linq raytracer).

Zauważ, że Scala i F # oba mają podobne koncepcje za-listowe i wyrażeń obliczeniowych obie będące monadycznego abstrakcje:

Scala:

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

F #:

monad { 
    let! x = expr1 
    let! y = expr2 
    return x + y 
} 
+0

Dziękuję za informacje. Zajrzę do tych tropów. – Joe

+0

Naprawdę, naprawdę dobre podsumowanie z miłym, łatwym do uchwycenia przykładem. +1 –

+0

Kontynuując na łączu raytracer, oto ten sam raytracer zaimplementowany całkowicie w jednym oświadczeniu LINQ: http://tirania.org/blog/archive/2007/Nov-16.html – JulianR

4

Poza tym, czytając książkę o tym, czy już używany LINQ? Zauważyłem, że jest to ogromny problem z moim codziennym programowaniem. Dla mnie to kolejny etap abstrakcji, który można wykorzystać do łączenia różnych źródeł danych, takich jak XML lub SQL, i pracy z nimi w tym samym "języku".

Co więcej, polecam ten interview with Anders Hejlsberg o programowaniu funkcjonalnym i LINQ.

+0

Dzięki za odpowiedź i link, przeczytam. Tak, użyłem go trochę (i uważam, że jest to bardzo przydatne), ale użyłem go w ten sam sposób, w jaki używałem mapy i w Scali. Zadałem to pytanie ze względu na podobieństwa i zastanawiałem się, jak głębokie one idą. – Joe

5

Bezdech jest prawdopodobnie przeznaczony do wszystkich tych "oczywistych" rzeczy, z których niektóre (jak drzewa ekspresji) są naprawdę doskonałe. Język jest tylko środkiem dostępu; czy jesteś podekscytowany słowem kluczowym throw lub jego funkcjonalnością?

+0

Nie miałem na myśli "oczywistych" rzeczy "było oczywiste, po prostu, że został uznany, ale nie jest przedmiotem mojego pytania! Być może sformułowałem to trochę słabo. – Joe

+0

Inni, proszę, przeczytaj komentarz Bena M w świetle mojej redakcji tego pytania. – Joe

2

LINQ był inspirowany przez HaskellDB, jak podano Erik Meijer, np w Confessions of a Used Programming Language Salesman (Getting the Masses Hooked on Haskell), więc nie jest ona sama w sobie nową koncepcją. Używanie tego samego języka do sprawdzania różnych źródeł jest do pewnego stopnia innowacyjne, chociaż naukowcy wcześniej wykazali, że model oparty na zagnieżdżaniu obejmuje XML, obiekty i relacyjne bazy danych. Dla mnie niezwykle fajne jest to, że został osadzony w popularnym języku ogólnego przeznaczenia i przede wszystkim obiektowym, czego wcześniej nie robiono.

Scala IMHO ma możliwości włączenia czegoś podobnego. Do tej pory, dla Scali, mamy ScalaQuery Stefan Zeiger i ScalaQL, które podążają śladami LINQ.

+0

Dziękuję za linki, one wyglądają bardzo ciekawy. – Joe

3

Rdzeń LINQ, składnia zapytań, w rzeczywistości nie ma ogromnego zasięgu.Jest to po prostu niektóre bardzo dosłowne tłumaczenia, sposobów i lambdas - tak

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

jest dosłownie:

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

że nic nie wie na temat metod rozszerzenie (chociaż są one najczęściej (ale nie tylko tylko), i nic o Expression itd. Liczba słów kluczowych (a więc i liczba wymaganych implementacji metod) nie jest duża. Jon próbowano wprowadzić je wszystkie w ciągu 1 godziny (w prezentacji na żywo). Nie zrobił źle ;-P


Być może bardziej imponująca część LINQ jest drzewo wsparcie wyrażenie, które było wymagane, aby umożliwić LINQ być wykorzystane przeciwko baz danych - czyli wyrażenia lambda, które mogą być skompilowany albo do delegata lub do modelu obiektowego, który reprezentuje napisany kod. Co ciekawe, ta sama idea prześwietla sposób, w jaki rozdzielczość DLR działa w wersji 4.0.

+0

Bardzo przydatna perspektywa. Dzięki za wytłumaczenie. – Joe