12.1.3.2 组合序列表达式

12.1.3.2 组合序列表达式

 

在 C# 中,yield return 关键字只能返回一个元素,因此,如果我们要在 C# 中,使用迭代器实现的方法中,产生整个序列,那么,就必须使用 foreach 循环,遍历序列中所有元素,逐个产生元素。这也能运行,但效率低下,特别是,如果用这种方式处理几个嵌套的序列。在函数式编程中,可组合性(composability)是一个更重要的概念,所以,F# 能够组合序列,使用专门的语言表达结构:yield!(通常发音 yield-bang),从序列表达式生成整个序列。清单 12.3 演示了以三种不同的方法生成城市序列。

 

清单 12.3 从不同的数据源组合序列 (F# Interactive)

> let capitals = [ "Paris";"Prague" ];;  <-- 首都列表

val capitals : string list

 

> let withNew(name) =  <-- 返回名字和名字加前缀

   seq { yield name

       yield "New " + name };;

val withNew : string ->seq<string>

 

> let allCities =

   seq { yield "Oslo"  [1]

       yield! capitals  [2]

       yield! withNew("York") };; [3]

val allCities : seq<string>

 

> allCities |> List.ofSeq;;

val it : string list = ["Oslo";"Paris"; "Prague"; "York"; "New York"]  <-- 把所有数据组合在一起

 

清单 12.3 首先创建两种不同的数据源。第一个是 F# 列表,有两个首都,值的类型是 list<string>;因为 F# 列表实现了 seq <'a> 接口,因此,在后面的代码中能够将它当作序列来使用。第二个数据源是函数,生成有两个元素的序列。接下来的代码段演示了将如何这两个数据源联接成一个序列。首先,使用 yield 语句返回一个值[1];接着,使用 yield! 结构返回 F# 列表中的所有元素[2];最后,调用 withNew 函数[3](返回一个序列),返回序列中的所有元素。从这里可以看出,可以在一个序列表达式中,混合使用两种产生元素的方法。

就像 yield 一样,yield! 结构也是延迟返回元素。就是说,当代码到达调用 withNew 函数时,这个函数才真正调用,而且,只返回表示该序列的对象。如果我们在函数中写的代码,放在 seq 块之前,它会在这一点上执行,但是,seq 块的主体并不会执行。它要到 withNew 函数返回之后才发生,因为我们需要生成下一个元素。当执行到达第一个 yield 结构时,它会返回元素,并将控制权返回到调用者。调用者然后执行其他操作,当调用者请求另一个元素时,序列的执行才恢复。

我们一直专注于序列表达式的语法,但是,只有开始使用,才不会觉得棘手。使用序列表达式时,有几个常用的模式,我们看其中的两个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值