繁体   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