码迷,mamicode.com
首页 > 其他好文 > 详细

12.1.3.1 写序列表达式

时间:2015-01-20 15:45:07      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:f#   函数编程   实用函数编程   序列表达式   

12.1.3.1 写序列表达式

 

在 C# 中,当我们实现返回 IEnumerable<T>、IEnumerator<T>,或对应的非泛型方法时,可以自动使用迭代器。F# 序列表达式使用 seq 标识符显式标记,而且不必要使用方法体或函数体。正如其名字所暗示的,序列表达式是表达式的不同类型,我们可以在代码中的任意位置使用。清单 12.2 演示了使用此语法,创建简单的序列。

 

清单 12.2 介绍序列表达式的语法 (F# Interactive)

 

> let nums =

    seq { let n = 10    [1]

        yield n + 1    [2]

        printfn "second.."   [3]

        yield n + 2 };;

val nums : seq<int>    [4]

 

写序列表达式时,我们把生成序列的整个 F# 表达式,括在一个 seq 块中[1]。块使用大括号,在开头使用 seq 标识符 1,表示编译器应该把块的主体解释为序列表达式。在后面我们将会看到,还有其他可能的标识符,指定其他选择性工作流。使用 seq 块,把整个表达式转换为延迟生成的序列,这从推断出的值类型中可以看到[4]。

序列表达式的主体可以包含具有专门含义的语句。与 C# 相类似,有从序列中返回元素的语句;在 F# 中,使用 yield 关键字[2]。主体也可以包含其他标准的 F# 结构,比如值绑定,甚至是执行有副作用的调用[3]。

类似于 C#,序列表达式的主体是延迟执行的。创建序列值(在前面示例中的值 nums)时,序列表达式的主体并不执行;只有访问序列中的元素时,才发生,每次访问一个元素时,序列表达式代码才执行,直到下一个 yield 语句。在 C# 中,访问迭代器中元素,最常用的是 foreach 循环。下面的 F# 示例,我们将使用 List.ofSeq 函数,把序列转换为不可变的 F# 列表:

 

> nums |> List.ofSeq;;

second..

val it : int list = [11; 12]

 

返回的列表包含序列生成两个的元素。这就是说,必须计算整个表达式,包括中途的执行 printfn 调用,因此,输出中包含来自序列表达式的打印行。如果我们只从序列中取一个元素,那么,序列表达式只计算到第一个 yield 调用,字符串不会打印出来:

 

> nums |> Seq.take 1 |> List.ofSeq;;

val it : int list = [11]

 

我们将使用Seq 模块中的一个序列处理函数,它只从序列中取一个元素。take 函数返回一个新的序列,参数指定元素的数量(示例中是 1),然后终止。我们可以将它转换为 F# 列表,就得到只包含一个元素的列表,但不调用 printfn 函数。

当我们实现序列表达式时,可能会遇到表达式主体太长的情况。在这种情况下,最自然的做法,就是将它拆分成几个生成序列部件的函数。如果序列使用多个数据源,我们可能要有在单独的函数中,读数据的代码。到目前为止,一切顺利,但是,还有一个问题,把从不同函数返回的序列组合起来。

 

------------------------------

1 你可能会感到奇怪,我们把 seq 称为标识符,而不关键字;后面会看到,它就是标识符(我们甚至可以自己定义),而不是 F# 语言中内置的、专门关键字。seq 标识符也不是由 seq <‘a> 类型自动定义的。名字虽然一样,但是在这里的seq 标识符是不同于由 F# 库定义的符号。

12.1.3.1 写序列表达式

标签:f#   函数编程   实用函数编程   序列表达式   

原文地址:http://blog.csdn.net/hadstj/article/details/42917941

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!