5.5.3.1 散函数应用(PARTIAL FUNCTION APPLICATION)

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

5.5.3.1 散函数应用(PARTIALFUNCTION APPLICATION)

 

要展示对函数的这种新理解情况,非常重要,让我们把注意力返回到列表。假设有一个数字列表,我们想要给列表中的每个数字都加上 10。在 F# 中,可使用 List.map 函数完成;在 C# 中,可以使用 LINQ 中的 Select 方法:

 

list.Select(n => n + 10)  ß C#

List.map (fun n -> n + 10) list  ß F#

 

这已经相当简单了,但如果我们已经有了前面示例中的 add 函数,还可以更简洁。List.map 期望第一个参数是int -> int 类型r 函数,即,函数的参数为一个整数,返回另一个整数。我们称这项技术为散函数应用(partial function application ):

 

> let add a b = a + b;;

val add : int -> int –> int  [1]

 

> let addTen = add 10;;

val addTen : (int -> int)  [2]

 

> List.map addTen [ 1 .. 10 ];;  [3]

val it : int list = [11; 12; 13; 14; 15;16; 17; 18; 19; 20]

 

> List.map (add 10) [ 1 .. 10 ];;  [4]

val it : int list = [11; 12; 13; 14; 15;16; 17; 18; 19; 20]

 

函数 add 的类型是 int -> int-> int[1]。因为我们现在知道它的真正意思,是函数的参数是一个整数,返回函数,因此,可以创建函数 addTen[2] ,通过调用只有第一个参数的 add,把 10 加到给定的参数值上;然后,把这个函数作为List.map 函数的参数值[3]。这有时很有用,但更重要的是,我们可以在为 List.map 函数指定第一个参数值时,直接使用散函数应用[5]。

函数 add 的类型是 int-> (int-> int),用一个数字作为参数值调用它,得到的结果类型是 int-> int,这正是 List.map 函数所需要的。当然,如果使用嵌套的 lambda 函数声明 add 函数,我们也可以用 C# 写同样的代码:

 

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

a => b => a + b;

list.Select(add(10));

 

正如我们在 F# 版本中看到的,调用 add 委托,得到的结果类型是 Func<int, int>,这与 Select 方法兼容。在 C# 中,使用有多个参数的 Func 委托,并使用另一个 lambda 函数为 Select 方法指定参数值,是更方便的,因为,语言支持更好。

 

注意

 

在使用散函数应用时,会听到一个术语科里化(currying)。它指的是,把有多个参数(比如元组)的函数,转换成只有第一个参数的函数,并返回有其余参数的函数,等等。例如,类型 int -> int-> int 的函数,是类型 (int *int)-> int 函数的科里化形式。那么,散函数应用就是不指定所有参数值的科里化函数的使用。

 

正如我们已经提到的,在F# 中选择正确的风格可能很难。使用元组写的代码,对于有大量的参数来说,有时更容易阅读,但它不能用于散函数应用。在本书的其余部分,我们将使用适合每种情况的风格,这样,就能获得哪个更好的直观理解。最重要的是,使用元组,是为了使代码更具可读性;使用散函数应用的风格,能提供明显的好处。在下一章讨论高阶函数时,我们将会看到有关后者的很好的示例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值