8.1.4 在 F# 中使用函数列表
来源:互联网 发布:安工大网络接入系统 编辑:程序博客网 时间:2024/06/03 12:50
8.1.4 在 F# 中使用函数列表
首先,我们声明一个表示有关客户信息的类型;客户有很多属性,因此,用F# 的记录类型表示最自然的选择,我们在前一章已经看过。清单 8.4 显示了类型声明,和所创建样本客户的代码。
清单 8.4 Client 记录类型和样本值 (F# Interactive)
> type Client =
{ Name : string; Income : int;YearsInJob : int
UsesCreditCard : bool;CriminalRecord : bool };;
type Client = (...)
> let john =
{ Name = "John Doe";Income = 40000; YearsInJob = 1
UsesCreditCard = true;CriminalRecord = false };;
val john : Client
这里没有什么新东西,我们声明了一个类型,并创建它的实例。为使清单更短,我们在声明类型,和创新值时,都没有为每个属性使用单独一行;在F# 中这是有效的,但必须在属性之间加上分号。使用轻量级语法,编译器会自动在行尾加上分号(如果需要分号),但是,当需要分行时,编译器就无能为力了,必须明确写上分号。
清单 8.5 完成这个示例。首先,创建测试列表,然后,确定是否提供贷款给前面清单中的样本客户(John Doe) 。
清单 8.5 执行测试 (F# Interactive)
> let tests = <-- 创建测试列表
[ (fun cl ->cl.CriminalRecord = true);
(funcl -> cl.Income < 30000);
(funcl -> cl.UsesCreditCard = false);
(funcl -> cl.YearsInJob < 2) ];;
val tests : (Client -> bool) list [1]
> let testClient(client) =
let issues = tests|> List.filter (fun f -> f (client)) [2]
let suitable =issues.Length <= 1 | 统计问题数,
printfn"Client: %s\nOffer a loan: %s (issues = %d)" client.Name | 输出结果
(if (suitable) then "YES" else "NO") issues.Length;; |
val testClient : Client –> unit
> testClient(john);;
Client: John Doe
Offer a loan: YES (issues = 1)
这是使用lambda 函数写初始化测试创建列表的常规语法,不必写出任何类型批注,F# 仍然能够正确推断出列表的类型[1]。F# 的类型推断非常智能,使用访问成员的名字就能推断出我们想要使用的记录类型。
在 C# 版本中,我们使用 Count 方法统计测试失败的数量;F# 没有对等的函数,我们既可以实现一个,也可以组合其他标准的函数,得到相同的结果。这里,我们采用第二种方法。首先,我们得到被认为是不安全客户的测试列表,可以通过使用 List.filter 返回结果为 true 的测试,然后,使用Length 属性,得到问题的数量。
在本节,我们学习了如何设计和使用基本的面向行为的数据结构,函数列表(a list of functions),在 C# 和 F# 中都有。在补充材料“无点式编程(Point-freeprogramming style)”中,我们会看到清单8.5 中用到的重要的函数技术。在下一节,我们会继续有关常见做法的讨论,就像我们讨论两个面向对象的设计模式和相关函数式结构一样。
无点式编程(Point-freeprogramming style)
我们见过很多例子,调用高阶函数时,不必显式写出 lambda 函数,那么,在清单 8.5 中这样做也行吗?程序的这种写法称为无点(point-free),因为我们在使用包含值(比如列表)的数据结构时,从来没有给结构中的值指定任何名字(特定的“点”)。我们用示例来演示已经见过的概念:
[1 .. 10] |> List.map ((+) 100)
places |> List.map (snd >>statusByPopulation)
第一种情况,我们处理一个数字集合,但是,没有任何符号表示列表中的值;第二种情况有点类似,只是处理的列表是元组,而且,没有用任何符号来表示元组或元组中的任何元素。
无点风格之所以可能,是由于有几项编程技术。第一行使用了散函数应用,这种方法是基于有大量参数的函数,创建有必要数量参数的函数。在我们的示例中,我们把中缀运算符 (+) 也看做普通函数。第二行使用了函数组合,这是另一项重要的构建函数技术,不必显式引用函数处理的值。
现在,我们看一下如何重写清单8.5 的示例。首先,我们要用管道运算符来重写 lambda 函数。
把:(fun f ->f client)
重写成:(fun f-> client |> f)
这两个函数意思相同。我们几乎完成,因为管道运算符把 client 作为第一个参数值,把函数作为第二个参数值。如果我们使用散应用来只指定第一个参数值(client),将得到一个函数,参数值为函数 (f),并将它应用到 client:
tests |> List.filter ((|>) client)
无点风格编程应始终用在刀刃上。虽然它使代码更简洁、典雅,但是,有时很难阅读和推理,我们在这里的演示就很重要。无点风格对于某些领域的函数编程是重要的,在第十五章,我们将会看到它在开发特定域语言时的用途。
- 8.1.4 在 F# 中使用函数列表
- 8.1.4 在 F# 中使用函数列表
- 使用 F# 列表
- 在C++拷贝构造函数中使用初始化列表
- 9.5 在 C# 中使用 F# 库
- Prototype使用$F()函数
- C++中使用初始化列表比在构造函数中对成员变量赋值更高效
- 在GVIM中显示函数列表!
- 在GVIM中显示函数列表
- 在本机代码中通过 COM 使用 F#
- 3.2.1.1 在 F# 中使用元组
- Python在函数中使用*和**接收元组和列表
- 在CComboBox组合框控件中 使用AddString()函数添加下拉列表项
- 在C + + 0 x新标准中,使用构造函数初始化列表和序列
- Python在函数中使用*和**接收元组和列表
- 在CComboBox组合框控件中 使用AddString()函数修改下拉列表项
- 使用初始化成员列表初始化数据与在构造函数中初始化数据
- Python在函数中使用*和**接收元组和列表
- 【引用】Java定时触发器
- 【引用】2011 程序员薪资调查报告
- 浅析gcc、arm-linux-gcc和arm-elf-gcc关系
- Dialong弹窗与PopWindow弹窗
- DES加密与解密的java实现
- 8.1.4 在 F# 中使用函数列表
- 【转载】Servlet监听器
- 64位windows安装tomcat支持jsp
- 根据日期、时间和当地经纬度计算太阳天顶角和方位角的原理
- 【转载】太阳天顶角 太阳高度角 太阳方位角
- 【转载】SQL Server dateTime类型 模糊查询
- 用mapXtreme Java开发web gis应用
- 【转载】Flex调用外部JS实现播放语音文件功能
- 【转载】HashMap的两种排序方式