12.1.1 使用高阶函数
在 F# 中,用于处理序列的函数在 Seq 模块中,我们将解释一个非常普通的函数,Seq.unfold。你可以看到,它与 fole 函数相对,它取一个集合,并把它"折"成单一值。unfold 取单一值,把它"展开"为一个序列。下面的代码片断展示了如何生成一个序列,包含把 10 个数字格式化为字符串:
> let nums = Seq.unfold (fun num –>
if (num <= 10) then Some(string(num), num + 1) else None) 0
;;
val nums : seq<string> = seq ["0"; "1"; "2"; "3"; ...]
num 值表示序列在生成过程中使用的状态。当第一次调用 lambda 函数时,num 的值设置为第二个参数的初始值 (在本例中为零)。Lambda 函数返回包含一个元组选项类型的值。None 值标志序列的末尾。当我们返回 Some 时,我们给它两个不同值在元组中:
■ 一个值,在序列中返回(这里,转换为字符串的数字)。
■ 另一个值,是新的状态,用于 lambda 函数下一次调用时。
如你所见,在输出中,返回值的类型是 seq<string>。这是一个 F# 类型,是 IEnumerable<string> 类型的别名。这是一种写相同类型的不同方式,同样,fold 是 System.Single 的 C# 别名,所以,可以自由地混合使用。输出还显示了序列的前面几个元素,因为这个序列可以是无穷的,F# Interactive shell 不会尝试输出所有的值。
标准的 .NET 库没有为 C# 包含一个类似的方法。在 C# 中,生成序列的方法是 Enumerable.Range(来自 System.Linq 命名空间),它返回的指定长度的数字升序序列(第二个参数), 从指定的起始数 (第一个参数)。我们可以在 C# 中实现类似 Seq.unfold 的函数,但我们将会看到,类似结果可以很容易地通过使用 C# 迭代,我们来看看下一步。
在 F# 中,用于处理序列的函数在 Seq 模块中,我们将解释一个非常普通的函数,Seq.unfold。你可以看到,它与 fole 函数相对,它取一个集合,并把它"折"成单一值。unfold 取单一值,把它"展开"为一个序列。下面的代码片断展示了如何生成一个序列,包含把 10 个数字格式化为字符串:
> let nums = Seq.unfold (fun num –>
if (num <= 10) then Some(string(num), num + 1) else None) 0
;;
val nums : seq<string> = seq ["0"; "1"; "2"; "3"; ...]
num 值表示序列在生成过程中使用的状态。当第一次调用 lambda 函数时,num 的值设置为第二个参数的初始值 (在本例中为零)。Lambda 函数返回包含一个元组选项类型的值。None 值标志序列的末尾。当我们返回 Some 时,我们给它两个不同值在元组中:
■ 一个值,在序列中返回(这里,转换为字符串的数字)。
■ 另一个值,是新的状态,用于 lambda 函数下一次调用时。
如你所见,在输出中,返回值的类型是 seq<string>。这是一个 F# 类型,是 IEnumerable<string> 类型的别名。这是一种写相同类型的不同方式,同样,fold 是 System.Single 的 C# 别名,所以,可以自由地混合使用。输出还显示了序列的前面几个元素,因为这个序列可以是无穷的,F# Interactive shell 不会尝试输出所有的值。
标准的 .NET 库没有为 C# 包含一个类似的方法。在 C# 中,生成序列的方法是 Enumerable.Range(来自 System.Linq 命名空间),它返回的指定长度的数字升序序列(第二个参数), 从指定的起始数 (第一个参数)。我们可以在 C# 中实现类似 Seq.unfold 的函数,但我们将会看到,类似结果可以很容易地通过使用 C# 迭代,我们来看看下一步。