2009-09-13 60 views
10

我正在研究LINQ,查詢語言出現(至少在表面上)只不過是在Haskell和其他FP語言中找到的映射和/或列表解析的實現(特別是'map'的泛化​​)和Scala中的'for')。它是否正確?除此之外,還有更多的語法嗎?從我正在閱讀的書(「Essential LINQ」)的令人喘不過氣的語氣看來,這裏看起來有些新穎或創新。LINQ有多少?

還有整個後端,管道,一階表達式樹和類型等來實現LINQ,但我的問題是關於查詢語言本身。

乾杯

回答

25

從功能上講,LINQ只不過是表達單子的句法簡化。對象(列表解析 - 即使這已經非常有用),你一直在談論,只是一個可能應用程序(類似List-Monad在Haskell)。

如果你寫

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

它只不過是

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

做到這一點具體的事情取決於用戶定義的LINQ提供程序(擴展的方法),其中Linq.Enumerable只是涉及IEnumerable■一個實現。

通過提供一個,您可以爲您的類型創建全新的LINQ語義。

示例:給定一個Option類型的計算失敗(可爲空值),可以定義一個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. 異步PROGRAMM流
  3. 也許-單子
  4. 列表理解
  5. 遞歸下降解析器
  6. 延期
  7. 迷你語言
  8. 並行計算(PLINQ)

一些鏈接:

與定點組合器相結合,Linq提供了一個完整的功能迷你語言(Linq raytracer)。

注意,Scala和F#都在換推導和計算表達式均爲一元抽象類似的概念:

斯卡拉:

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

F#:

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

謝謝你的信息。我會研究這些線索。 – Joe 2009-09-13 16:57:10

+0

真的很好,總結一個很好的,易於掌握的例子。 +1 – 2009-09-13 17:07:50

+0

繼續在raytracer鏈接上,下面是完全在單個LINQ語句中實現的相同raytracer:http://tirania.org/blog/archive/2007/Nov-16.html – JulianR 2009-09-13 17:37:39

4

除了看書吧,你已經使用LINQ?我發現它在我的日常編程工作中是一個巨大的倍頻器。對我來說,這是抽象的下一個步驟,它可以用來合併不同的數據源,如XML或SQL,並以相同的「語言」使用它們。

此外,我建議這個interview with Anders Hejlsberg關於函數式編程和LINQ。

+0

感謝您的回覆和鏈接,我會讀它。是的,我已經使用了一些(我發現它確實非常有用),但我使用的方式與我一直在使用map和Scala中的方法相同。我問這個問題是因爲它們的相似之處,並且想知道它們有多深。 – Joe 2009-09-13 16:52:52

5

呼吸困難可能是針對所有那些「明顯」的東西,其中一些(如表達樹)非常出色。語言只是一種訪問手段;您是否對throw關鍵字感到興奮,或者對其暴露的功能感到興奮?

+0

我並不是說這個''顯而易見'的東西'是顯而易見的,只是它被公認,但不是我的問題的焦點!也許我說得差一點。 – Joe 2009-09-13 16:55:08

+0

其他請閱讀本M的評論,因爲我對這個問題的編輯。 – Joe 2009-09-13 17:01:02

2

LINQ的靈感由HaskellDB,因爲Erik Meijer已經無數地陳述,例如在Confessions of a Used Programming Language Salesman (Getting the Masses Hooked on Haskell),所以它本身並不是一個新概念。儘管嵌套關係模型涵蓋了XML,對象和關係數據庫這一事實,研究人員以前已經展示過,但使用相同的語言來查詢不同的數據源在某種程度上是創新性的。對我而言,非常酷的是它已經嵌入到一個流行的,通用的,主要面向對象的語言中,這是以前沒有做過的。

斯卡拉恕我直言,有能力合併類似的東西。到目前爲止,對於Scala,我們有Stefan Zeiger的ScalaQuery和Daniel SpiewakScalaQL,它遵循LINQ的腳步。

+0

感謝您的鏈接,它們看起來很有趣。 – Joe 2009-09-13 16:59:34

3

查詢語法LINQ的核心範圍並不是很大。這只不過是一些非常字面翻譯,方法和lambda表達式 - 所以

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等。關鍵字的數量(以及因此所需的方法實現的數量)並不是很大。 Jon曾經試圖在1小時內實現所有這些(在現場演示中)。他沒有做得太慘;-p


也許LINQ的更令人印象深刻的是,被要求允許對數據庫使用LINQ的表達式樹支持 - 即lambda表達式,可以是將代碼編譯爲代表,以代表寫入代碼的對象模型。有趣的是,這個相同的想法照亮了DLR解決方案在4.0中的工作方式。

+0

一個非常有用的觀點。感謝澄清。 – Joe 2009-09-13 19:41:59