12.3.2.2 使用查询和序列表达式

728 篇文章 1 订阅
349 篇文章 0 订阅

12.3.2.2 使用查询和序列表达式

 

在 C# 3.0 中,我们可以使用新的查询表达式语法,写有关映射和筛选数据的操作。查询表达式还支持许多其他操作,但我们会只关注映射和筛选,来演示函数技术和 F# 功能。

F# 虽然没有专门提供的查询表达式,但是,使用序列表达式,仍可以轻松地写出映射和筛选数据的查询。这是因为序列表达式在 F# 中所有地方都可以使用,而不仅仅是返回序列的函数。清单 12.9 显示了使用 C# 中的查询和 F# 中的序列表达式,实现我们前面的示例。

 

清单 12.9 在 C# 和 F# 中的筛选和映射序列

C#

F#

var nums1 =

  from n in nums

  where n%3 == 0

  select n * n;

let nums1 = seq {

  for n in nums do

    if (n%3 = 0) then

      yield n * n }

 

在 C# 中,查询表达式和迭代器是完全不同的,而在 F# 中,序列表达式表明,它们在概念上是相关的。查询表达式中的每个部分在 F# 中都有对应的结构,而且总是更加一般:from 子句由简单的 for 循环取代,where 子句由 if 条件取代,select 子句与有映射的 yield 语句相对应,表示为通常的计算。

C# 查询表达式语法还有另外一些运算符,用 F#序列表达式不容易表达。因此,C# 版本功能更强大,而 F# 的实现更加统一。

要注意一下C# 查询表达式和 F# 序列表达式内部的运行。C# 查询表达式使用 lambda 表达式,以明确的定义转化成一系列调用,比如:Where、Select、SelectMany、Join 和 GroupBy。这些通常是扩展方法,但也不一定,编译器不关心查询表达式的意思,只要翻译的代码是有效的就行。这个“数据源不可知论(datasource agnosticism)”对于数据处理的方法,比如LINQ to Objects 和 LINQ to SQL,至关重要,我们不久将使用它,展示查询语法如何用来处理其它种类的值。

另一方面,序列表达式能够表达更加复杂和多方面的结构。我们可以复制 yield 结构,把数据源中的一个项目返回为两个元素。这个使用 C# 中的迭代器可以很容易实现,但是,使用内嵌的查询语法,表示这种转换,是不可能的。

 

LINQ 中的其他查询运算符

 

在 C# 3.0 中,查询表达式语法是专为从各种数据源查询和格式化数据的,因此,它的操作不止映射和筛选。这些运算符主要就为此目的,在 F# 中没有专门对应的语法。所有这些标准运算符都可以用操作序列的常规高阶函数来实现。例如,排序数据:

var q =

  from c in customers

  orderby c.Name

  select c;

[

合理的话,这里也应该是 C.City

]

let q =

  customers

  |> Seq.sortBy (fun c -> c.City)

作为给 Seq.sortBy 运算符的第一个参数的函数,指定在比较两个元素时,应该处理元素的哪个属性。在 C# 的查询语法中,对应于跟在  orderby 子句后的表达式;C# 编译器使用 lambda 函数,将此表达式转换为对标准OrderBy 方法的调用。F# 中唯一查用的操作,是作为高阶函数的分组:

var q =

  from c in customers

  group c by c.City;

let q =

  customers

  |> Seq.groupBy (fun c -> c.City)

对序列进行分组,需要指定返回键的函数,键表示元素所属的组。C# 还是有专门的语法,而在 F# 的代码段中,我们使用标准的 lambda 函数。

在这些示例中,两个版本的代码看起来是合理的。然而,当我们写 F# 的代码,需要操作把只能使用高阶函数的映射和筛选混到一起,那么,等效的 C# 查询表达式会更容易理解。

 

在 F# 编译器中,序列表达式的实现进行了优化,但是,如果没有这些优化,它可能与 C# 查询表达式一样运行。任可序列表达式,都可以转化为标准的函数调用序列。类似于 C#,我们可以提供这些函数的自定义实现,这样,就可以更深入理解 F# 中转换是如何运行的。F# 语言使用数量很少的操作,严重依赖于一个操作,称为平面映射(flattening projection)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值