3.4.1.2 在 F# 中传递函数作为参数值

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

3.4.1.2 在 F# 中传递函数作为参数值

 

在 F# 中的函数 aggregateList 非常类似于我们已经实现的方法,但有一点重要的区别,F# 天然支持把函数作为参数值传递给其他函数,因此,不需要使用委托。

在 F# 中,函数是特殊类型。类似于元组,函数的类型是由其他的基本类型构成。元组类型的代码表示,在元素的类型之间使用星号(例如,int * string);而函数的类型表示,参数的类型和返回的类型。它提供了与 C# 中的委托所实现的同样的类型安全。一个函数,如果取一个数,加上 1,它的类型为 int -> int,表示取一个整数,返回一个整数;如果函数取两个整数,返回一个整数,其类型为 int -> int-> int,这就是 aggregateList 函数第一个参数的类型。清单3.18 是示例的 F# 版本。

 

清单 3.18 计算列表中元素的和、积(F# Interactive)

> let rec aggregateList (op:int ->int -> int) init list =  <- 函数作为参数

 match list with

  |[] -> init    [1]

  |hd::tail ->

    letresultRest = aggregateList op init tail |  [2]

    opresultRest head                   |

;;

val aggregateList : (int -> int ->int) -> int -> int list -> int

 

> let add a b = a + b

  letmul a b = a * b

  ;;

val add : int -> int -> int    |  显示的类型与 op 参数的类型一致

val mul : int -> int -> int    |

 

> aggregateList add 0 [ 1 .. 5 ];;  |  立即类型函数

val it : int = 15               |

> aggregateList mul 1 [ 1 .. 5 ];;  |

val it : int = 120              |

 

如同 C# 版本一样,函数的前两个参数说明列表中的元素如何聚合,第二个参数是初始值,第一参数是 F# 函数。在这个示例中,为了使代码更简单,我们只让函数使用整数,因此,第一个参数加上了类型批注(type annotation),说明 op 函数的类型是有两个整数参数,返回一个整数的函数。

接下来,我们看到熟悉的列表处理模式:一个分支用于空列表[1],一个用于 cons cell [2]。在 F# Interactive 中输入 AggregateList 函数的代码后,输出了函数的签名(signature of the function) [3]。函数的签名,第一次看到有点不知所措,但很快就会熟悉了。图 3.2 是签名每部分的意思。

 

图 3.2 aggregateList 函数的类型签名的详细信息。第一个参数值指定如何聚合两个数字,第二个是初始值,第三个是输入的列表。

 

最后,我们写了两个简单的函数(add 和 mul)来验证,它们的签名都与 aggregateList 函数的第一个参数的类型相对应。我们写的这两个函数,只是想使示例与前面的 C# 版本保持一致,实际上,F# 能够取任意二元运算符作为参数,把它当作普通的函数一样使用。因此,我们不一定要写加法函数,而直接用加号:

 

> aggregateList (+) 0 [ 1 .. 5 ];;

val it : int = 15

 

直接使用运算符,这个功能通常很有帮助,使 F# 代码非常简洁。注意,当使用运算符代替函数时,必须把它括在括号中,不能只写 +,必须要写成 (+)。

我们可能会想,aggregateList 函数不是特别有用,除了加(乘)列表中的元素以外,没有其它用途,但下一节,会有更惊奇的例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值