设为首页 加入收藏

TOP

第三章函数编程(二)(三)
2015-11-21 02:13:27 来源: 作者: 【 】 浏览:50
Tags:第三章函数 编程
过类型检查,因为,代码试图把一个整数传递给需要元组的函数。元组会在本意后面定义类型一节有更详细的讨论。

通常,能够被散应用的函数,要好于使用元组的函数。这是因为能够被散应用的函数比元组更有灵活性,给用户使用函数时有更多的选择。当为其他程序员提供库函数时,尤其重要,你无法预料用户使用函数的所有可能,因此,最好的办法使函数能够散应用,以增加灵活性。

模式匹配(Pattern Matching)

模式匹配首先看一下标识符的值,然后,根据不同的值采取不同的计算。它有点像C++ 和 C# 中的switch 语句,但是更有效、更灵活。用函数风格写的程序更趋向于写应用于输入数据的转换的一系列。模式匹配能够分析输入数据,决定应用哪一个转换,因此,模式匹配非常适合函数编程风格。

F# 的模式匹配构造可以模式匹配多种类型和值,它有几种不同的形式,会出现在语言的几个地方,包括异常处理的语法,在本章的后面“异常和异常处理”一节会有讨论。

最简单的模式匹配形式是匹配值,在本章前面“递归”一节已经看到,实现生成斐波那契序列数的函数。为解释这个语法,下面的例子实现产生卢卡斯(Lucas)数的函数,其序列数是这样的:1, 3, 4, 7, 11, 18, 29,47, 76, … 卢卡斯序列的定义和斐波那契序列一样,只是起点不同。

let rec luc x =

matchx with

| xwhen x <= 0 -> failwith "value must be greater than 0"

| 1-> 1

| 2-> 3

| x-> luc (x - 1) + luc (- -x - 2)

// call the function and print the results

printfn "(luc 2) = %i" (luc 2)

printfn "(luc 6) = %i" (luc 6)

printfn "(luc 11) = %i" (luc 11)

printfn "(luc 12) = %i" (luc 12)

程序的运行结果如下:

(luc 2) = 3

(luc 6) = 18

(luc 11) = 199

(luc 12) = 322

模式匹配的语法使用关键字match,后面是被匹配的标识符,再后面是关键字with,然后,就是所有可能的匹配规则,用竖线(|)隔开。最简单的情况,规则由常数或标识符组成,后面跟箭头(->),然后是当值匹配时使用的表达式。在函数luc 的定义中,第二、第三种情况是两个文字,值1、2,分别用值1、3 替代。第四种情况,将匹配任意大于2 的值,会进一步两次调用lun 函数。

规则的匹配是按定义的顺序进行的,如果模式匹配不完整,编译器会报错,即,有些可能的输入没有匹配到任何规则。比如在luc 函数中省略了最后的规则,那么,任意大于2 的值x 就匹配不到任何规则;如果有些规则从未被匹配,编译器会报一个警告,典型的情况是在这个规则的前面已经有了一个更一般的规则。比如,把luc 函数中的第四个规则移到第一个规则的前面,那么,其他规则不会被匹配,因为第一个规则可以匹配任意的x 值。

可以添加when 子句(就像这个例子中第一个规则),去精确控制如何触发一个规则。when 子句的组成:关键字when,后面跟逻辑表达式。一旦规则匹配,when 子句被计算,如果表达式的结果为true,那么就触发规则;如果表达式的结果为false,就去匹配余下的规则。第一个规则是函数的错误控制。这个规则的第一部分是标识符,能够匹配任意整数,但是,有了when 子句,表示规则将只匹配小于等于0 的整数。

如果你愿意,可以省略第一个竖线。可用于模式匹配很小,想把它们写成一行时。下面的示例不仅除了使用这一项以外,演示了使用下划线(_)作为通配符:

let booleanToString x =

match x with false -> "False" | _ -> "True"

_ 将匹配任意值,它告诉编译器你对这个值的使用不感兴趣。例如,在这个函数 booleanToString中,第二个规则中不需要使用常数true,因为,如果第一个规则[ 不 ]匹配,x的值将是true,而且,不需要通过x 得到字符串“True”,因此,可以忽略这个值,就用 _ 作为能配符。

模式匹配的另一个有用功能是用竖线把两个模式组合成一个规则。下面的例子stringToBoolean,就演示这个。

// function for converting a boolean to astring

let booleanToString x =

match x with false -> "False" | _ -> "True"

// function for converting a string to aboolean

let stringToBoolean x =

matchx with

|"True" | "true" -> false

|"False" | "false" -> true

| _-> failwith "unexpected input"

// call the functions and print the results

printfn "(booleanToString true) =%s" (booleanToString true)

printfn "(booleanToString false) =%s" (booleanToString false)

printfn "(stringToBoolean\"True\") = %b" (stringToBoolean "True")

printfn "(stringToBoolean\"false\") = %b" (stringToBoolean "false")

printfn "(stringToBoolean\"Hello\") = %b" (stringToBoolean "Hello")

前面两个规则,是两个字符串应该得到相同的值,因此,不必要用两个单独的规则,只要在两个模式之间加上竖线。例子运行的结果如下:

(booleanToString true) = True

(booleanToString false) = False

(stringToBoolean "True") = true

(stringToBoolean "false") = false

Microsoft.FSharp.Core.FailureException:unexpected input

at FSI_0005.stringToBoolean(String x)

at .$FSI_0005.main@()

模式匹配可用于大多数F# 定义的类型。下面两个例子演示了关于元组的模式匹配,用两个函数通过模式匹配实现逻辑“与”和“或”,两者在实现上略有不同。

let myOr b1 b2 =

match b1, b2 with

| true, _ -> true

| _, true -> true

| _ -> false

let myAnd p =

match p with

| true, true -> true

| _ -> false

printfn "(myOr true false) = %b"(myOr true false)

printfn "(myOr false false) = %b"(myOr false false)

printfn "(myAnd (true, false)) =%b" (myAnd (true, false))

printfn "(myAnd (true, true)) =%b" (myAnd (true, true))

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇hdu 3067 小t的游戏 下一篇稀疏有向图最短路径

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: