`
tianshibaijia
  • 浏览: 1128679 次
文章分类
社区版块
存档分类
最新评论

8.3.1 函数的记录

 
阅读更多

8.3.1 函数的记录

我们已经看到一个处理多个函数的方式。在前面的示例中,我们返回一个函数元组作为结果,可以用相同的技术,来表示有新的报表功能的应用程序。我们说,这个报表函数取客户端、打印一些内容到屏幕上,返回 unit 作为结果。使用这种表示,行为列表的类型将是

((Client -> bool) * (Client -> unit)) list

开始,看起来有点可怕,很复杂,函数没有名字,代码不具可读性。在前面的示例中,这并不是一个大问题,因为,这个函数只在本地使用,但是,这个清单是我们的应用程序的一个关键数据结构,所以,它应该尽可能清晰。使代码更具可读性的一个简单的解决方案,是使用记录类型,而不是元组。我们可以像这样来定义它:

type ClientTest =
{ Check : Client –> bool
Report : Client -> unit }

此代码定义了两个字段的记录,两者都是函数。这只是以相同方式,像任何其他类型一样使用函数的另一个例子。这个声明类似于很简单的对象(或接口),我们将在以后讨论这种相似性。首先,让我们看一下清单 8.11,显示了如何创建使用较早前声明的记录表示检查的列表。

Listing 8.11 Creating tests with reporting (F#)

let checkCriminal(client) = client.CriminalRecord = true
let reportCriminal(client) =
printfn "Checking 'criminal record' of '%s' failed!" client.Name

let checkIncome(client) = client.Income < 30000
let reportIncome(client) =
printfn "Checking 'income' of '%s' failed (%s)!"
client.Name "less than 30000"

let checkJobYears(client) = client.YearsInJob < 2
let reportJobYears(client) =
printfn "Checking 'years in the job' of '%s' failed (%s)!"
client.Name "less than 2"

let testsWithReports =
[ { Check = checkCriminal; Report = reportCriminal };
{ Check = checkIncome; Report = reportIncome };
{ Check = checkJobYears; Report = reportJobYears };
(* more tests... *) ]

清单 8.11 是一系列的 let 绑定。为使代码更具可读性,我们没有使用 lambda 函数,而是把所有的检查定义为普通的 F# 函数。对于每个检查,我们已经定义一个有前缀 check 的函数和一个前缀 report 的函数。如果在 F# Interactive 中输入代码,可以看到这个函数类型对应到 ClientTest 记录类型的类型。最后一个操作创建一个检查列表。我们需要为每个条件创建一个记录,存储两个相关函数,并创建一个包含这个记录值的列表。

我们也要更新检查特定客户的函数。首先找到这些失败的检查(使用 Check 字段),然后,让它们打印结果 (使用 Report 字段)。清单 8.12 显示这个修改函数,以及根据我们示例客户运行它时的输出。

Listing 8.12 Testing a client with reporting (F# Interactive)

> let testClientWithReports(client) =
let issues =
testsWithReports
|> List.filter (fun tr -> tr.Check(client))
let suitable = issues.Length <= 1
for i in issues do
i.Report(client)
printfn "Offer loan: %s"
(if (suitable) then "YES" else "NO")
;;
val testClientWithReports : Client -> unit

> testClientWithReports(john);;
Checking 'years in the job' of 'John Doe' has failed (less than 2)!
Offer loan: YES

自清单 8.5 以来,testClient 函数只略有改变。第一个变化是在选择那些检查失败的行中。这个清单现在是记录的集合,所以,我们必须使用存储在 Check 字段中的函数来检查客户。第二个改变是,早先,我们感兴趣的只是在一些未能通过的检查。这一次,我们还需要打印有关这个失败的详细信息,使用命令式的 for 循环实现,为所有失败的检查调用 Report 函数。

代码的当前版本的一个问题是,在创建一些检查时,我们不得不写非常相似的函数。让我们来解决它,以减少不必要的代码重复。

分享到:
评论

相关推荐

    用Javascript设计通用日历控件及其与ASP的结合应用

    8.3.1 函数说明 37 8.3.2 代码说明 37 8.4 cancelMonth 38 8.4.1 函数说明 38 8.4.2 代码说明 38 8.5 cancelDay 39 8.5.1 函数说明 39 8.5.2 代码说明 39 第九章 美化效果模块的设计与实现 41 9.1 函数说明 41 9.2 ...

    C++高级参考手册 完全自学 内容详细 讲解通俗易懂

    6.10.2 一个简单的数据记录 6.11 小结 6.12 练习 第7章 常量 7.1 值替代 7.1.1 头文件里的const 7.1.2 const的安全性 7.1.3 集合 7.1.4 与C语言的区别 7.2 指针 7.2.1 指向const的指针 7.2.2 const指针 ...

    Visual C++ 2005入门经典.part08.rar (整理并添加所有书签)

    8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 ...

    Visual C++ 2005入门经典.part04.rar (整理并添加所有书签)

    8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 ...

    C++编程思想习题

    6.10.2一个简单的数据记录 6.11小结 6.12练习 第7章 常量 7.1值替代 7.1.1头文件里的const 7.1.2const的安全性 7.1.3集合 7.1.4与C语言的区别 7.2指针 7.2.1指向const的指针 7.2.2const指针 7.2.3赋值和类型检查 7.3...

    Visual C++ 2005入门经典.part07.rar (整理并添加所有书签)

    8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 ...

    Visual C++ 2005入门经典.part09.rar (整理并添加所有书签)

    8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 ...

    Visual C++ 2005入门经典.part05.rar (整理并添加所有书签)

    8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 ...

    Visual C++ 2005入门经典.part06.rar (整理并添加所有书签)

    8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 ...

    linux programming instances网络编程教程 附源代码

    8.3.1 ioctl函数 8.3.2 fcntl函数 8.4 本章小结 提 高 篇 第9章 进程间通讯的同步 9.1 互斥锁 9.1.1 互斥锁的基本原理 9.1.2 互斥锁的基本操作函数 9.1.3 编程实例 9.2 条件变量 9.2.1 条件变量的...

    C++编程思想.pdf

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向...

    C++编程思想 例子和叙述讲解C++编程

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向...

    C++编程思想

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向...

    C++编程思想 PDF

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 ...

    C++编程思想.rar

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向...

    c++ 编程思想 (高清pdf)

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向...

    C++编程思想(程序员必读)

    6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向...

Global site tag (gtag.js) - Google Analytics