5.5.3 多参数函数

来源:互联网 发布:n86软件下载 编辑:程序博客网 时间:2024/05/22 10:24

5.5.3 多参数函数

 

我们回顾一下,写函数时的选项。在 F# 中,当写的函数有多个参数时,可以使用元组。下一个示例以这种风格写的函数,计算两个整数的和;我们将使用 lambda 函数语法,但在 F# 中,也可以使用简单的 let 绑定,得到同样的结果:

 

> let add = fun (a, b) -> a + b;;

val add : int * int -> int

 

从类型签名中可以看到,函数有一个值参数,是元组形式 (int * int),返回类型为 int。对应的 C# 的 lambda 函数,可以写成这样的形式:

 

Func<int, int, int> add =

  (a,b) => a + b

 

Func < int, int, int> 委托表示的方法,有两个int 类型的参数,并返回一个 int 类型,因此,类似于 F# 中的元组;调用函数时,也可以看到这种相似性:

 

let n = add(39, 44)

var n = add(39, 44)

 

这个语法与在F# 中调用以元组作为参数的函数(第一行),调用 C# 中的 Func 委托(第二行)是一样的。现在,我们在 F# 中写同样的代码,使用传统的 F# 样式,写有多个参数的函数:

 

> let add = fun a b -> a + b;;

val add : int -> int -> int

 

奇怪吗,这与我们早先看到的返回函数时的签名相同,也可以读作int-> (int-> int)。它可能是这样的函数,取第一个参数,计算加法,返回一个函数;那么,结果是取第二个参数值的函数。现在,我们按这种方式,可以重写代码,使用两个嵌套的 lambda 函数:

 

> let add = fun a -> fun b -> a +b;;

val add : int -> int -> int

 

如果你第一次接触这种概念,可能会奇怪。一个函数返回另外一个函数,怎么能和有两参数并返回一个整数的函数相同呢?有一个参数的函数,怎么能和有两个参数的函数相同呢?如果不能马上理解,也不要太担心,我敢保证,你最终会理解的。在看过更多的示例之后,可能想回到这一节,就会容易领会这个概念了。

 

有多个元素的元组

 

如果要在 C# 中使用 .NET 4.0,创建具有两个以上元素的元组,可以使用重载的 Tuple 类,它提供的重载,表示元组包含的元素从一个到八个。我们在第三章实现的 C# 类,有更多的限制,只支持两个元素。不管我们实现了多少个重载,总是有限制。

不过,有一种方法可以突破这种限制。让我们看一下,如何使用第三章的 Tuple<A, B> 类型,表示 F# 的类型 int * string * bool。方法也很简单,为了保存比元组类型提供的元素更多,可以嵌套元组:

 

Tuple<int, Tuple<string, bool>>tup = (...);

 

当我们像这样声明变量时,它会包含三个值。为了得到整型值,可以写成 tup.Item1;要访问字符串值,写成 tup.Item2.Item1;最后,布尔值保存在 tup.Item2.Item2 中。

这有点类似于嵌套函数,比如 F# 类型 int -> (string -> bool),但在元组和函数之间也有不同。此处所示的函数类型,是与 int -> string –> bool相同的,而有三个元素的 F# 元组 (int *string * bool),与嵌套元组的类型,比如 int * (string * bool),是不同的。

 

你可能想知道,是否有办法用 C# 3.0 重写我们前面的示例,确实可以。不是创建 Func<int, int, int> 类型的委托,可以创建Func<int, Func<int, int>> 类型的委托,这更接近于签名为int-> (int-> int) 的 F# 函数:

 

Func<int, Func<int, int>> add =

a => b => a + b;

int n = add(39)(44);

 

用两个 lambda 函数写这个声明,,就像我们前面的 F# 示例。当用这个委托计算加法时,必须调用第一个委托,它返回另一个委托;然后,调用第二个委托。在 F# 中,这是完全正常的、使用函数的方法,编译器会进行优化,使之更有效率。

这一点非常重要,但是,你可能会想,用这种方式,函数应该在哪里拆分呢?结果是惊人的强大。

0 0
原创粉丝点击