簡體   English   中英

在 F# 中使用 LINQ?

[英]Using LINQ in F#?

Given that the basic syntax and semantics of a language like F# are already designed to provide exactly what LINQ provides to C#/VB as an add one, why should I be using LINQ when programming in F#? 我得到了什么,又可能失去什么?

LINQ有兩個方面。 一個是語言方面,例如在 C# 中有(上下文)關鍵字,例如fromselect where您可以在其中編寫類似 SQL 的代碼,這些代碼對IEnumerable s 和諸如此類的東西進行查詢。 這是一個相對較薄的語法糖層,它轉換為 LINQ 庫調用SelectSelectMany以及Where等等。

然后是IQueryable方面,它可以將相同的代碼具體化為IQueryable ,這實際上很像引用機制,因為它具體化了構造查詢的語法樹。 這是必不可少的,因為不同的提供者可以插入行為以以自己的方式“編譯”代碼,例如 SQL 提供者可以獲得“完整查詢”視圖並使用將在服務器(與將 SQL 數據庫視為IEnumerable行並僅加載 memory 中的所有行並在 .NET 中過濾它們的天真方法相反,或者只是將您的客戶端嚴重落在大數據上,這會在內部應用)。

第一個方面只是語法糖等等。 F# 2.0 (the F# version in VS2010) has no intrinsic support for LINQ, but the PowerPack has a LINQ bridge so that you can use F# quotations of normal F# Seq combinators as a way to express LINQ queries.

不過,就整體技術而言,第二個方面更為重要。 LINQ 是關於具體化查詢,以便程序員可以聲明式地指定意圖,然后各種提供者可以插入系統並將該意圖轉換為相應的數據后備存儲的有效執行計划。 .NET 3.5。 表達式樹類型是 LINQ 的這一基本方面的“接口”,因此任何給定的編程語言只需要某種方式讓程序員編寫將生成這些表達式樹的表達式。

所以我不覺得原來的問題很有意義。 使用 LINQ 的根本原因是因為您想要查詢 SQL 數據庫(或 OData 提要,或......),以使查詢在服務器上高效運行(或不需要使用一百萬個重復的 Z293C9EA、246FFF9989A26 請求)或...),並且您希望以一種不需要您對這些技術的詳細信息了解太多的方式進行操作(各種 LINQ 后端提供商具有所有單獨的特定領域的智能)。 語法大多只是語法,不同的語言可能有不同的糖(或糖化機制)來以對給定編程語言慣用的方式編寫 LINQ 查詢。

LINQ,從語言的角度來看(C# 的特殊 from... 語法)幾乎是不必要的,因為 F# 已經能夠非常簡潔地表示類似 LINQ 的數據轉換。 我懷疑 C# 糖的大部分剩余目的是重組代碼,以便 C# 可以鍵入 LINQ 查詢,而無需強制用戶手動提供類型注釋或執行擴展。 這在 F# 中也是不必要的。

至於在 F# 中使用 System.Linq 命名空間,我不推薦。 F# 類型推斷在成員訪問方面變得更加愚蠢。 我懷疑使用 System.Linq 需要比使用相應的 F# 庫更明確的類型注釋。 即使在類型推斷成功的情況下,與本機庫相比,在 F# 中,非柯里化 CLR 樣式的 API 通常也會讓人感到沉重和格格不入。

沒錯,對於內存 collections F# 通過各種收集模塊、 SeqList等提供了 LINQ 中的大部分行為。 我相信 LINQ 的顯着特點是查詢提供程序的可插入性。 雖然 F# 通過報價提供有限的元編程支持, 但我知道沒有任何簡單的方法可以將這些轉換為對不同的后備商店有意義的東西 (PowerPack 在 F# 中對此提供了一些支持)。

要回答您的問題,如果您打算翻譯查詢而不是針對內存中的 collections 執行查詢,那么 LINQ 是您的最佳選擇。 否則,請堅持使用 F# 收集模塊。 通過在這些足夠的情況下使用 LINQ,您會犧牲部分 function 應用程序,function 鏈接(管道),並且您可能會編寫其他非代碼代碼。

我同意@blucz 的回答,不建議這樣做,但如果你真的想要,它看起來像這樣:

導入System及系統System.Linq

open System
open System.Linq

包裝一些LINQ擴展方法

let select  f xs = Enumerable.Select(xs, new Func<_,_>(f))
let where   f xs = Enumerable.Where(xs, new Func<_,_>(f))
let orderBy f xs = Enumerable.OrderBy(xs, new Func<_,_>(f))

並使用它

[1..100] 
|> where (fun x -> x > 2) 
|> select (fun x -> x * 2) 
|> printfn "%A"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM