第七章 F# 库(一)

第七章 F# 库(一)

 

虽然 F# 可以使用 .NET BCL中的所有类,但它自己也提供了一组库。

[

现代汉语中使用单字名词的已经很少了,因此,libraries有时译成库,有时译成库函数。严格来讲译成库函数是不准确的,因为,库中肯定不止包含函数。

]

F# 库分成两部分,一个是 FSharp.Core.dll,也称为 F#核心库(F# core library)或本机 F#库(native F# library);另一个是 FSharp.PowerPack.dll,有时直接就称 power packF#核心库包含了 F# 编译器运行所需要的一切。比如,它包含元组(Tuple)类,用于处理元组;power pack F# 核心库补充了其他有用的功能。把库分成两部分,有两个主要的原因:第一,努力使核心库保持尽可能小,这样,应用程序的开发人员努力使对 FSharp.Core.dll的依赖占据小的空间,而不致引起大的问题;第二,也可能更重要,使 FSharp.Core.dll保持尽可能稳定,这样,只随新版本的编译器而改变,而 F# 的团队发布新版本的 FSharp.PowerPack.dll,这里会有更多有趣的新的功能。

本章的目标不是成为介绍 F# 库中类型和函数的完整文档,它只是一个概览,知道模块能名做什么,特别关注那些在 BCL 中没有的功能。F# 的在线文档(http://msdn.microsoft.com/fsharp)可以找到每一个函数的详细文档。

 

 

本机 F# FSharp.Core.dll

 

本机 F# 库包含了编译器能够运行的所有类,比如,F#列表编译的类型定义。我们将讨论下列几个模块:

Microsoft.FSharp.Core.Operators:这个模块中包含了数学运算符的函数。

Microsoft.FSharp.Reflection:这个模块中包含的函数,用于补充 .NET框架的反映类型,为了获得 F# 类型和值的更精确视图。

Microsoft.FSharp.Collections.Seq:这个模块中包含的函数用于处理所有支持 IEnumerable接口的类型。

Microsoft.FSharp.Text.Printf:这个是用于字符串的模块。

Microsoft.FSharp.Control.Event:这个是用于处理 F#事件的模块。

 

 

运算符(Microsoft.FSharp.Core.Operators)模块

 

F# 中,运算符是由库定义的,而不是语言内置的。这个模块包含了一些语言的运算符;还包含了一些有用的运算符,比如函数,这些也正是我们将要讨论的。这个模块默认被引用,就是说,用户可以使用其中的函数,而不要前缀。我们将专门讨论下面几个函数类型:

算术运算符(Arithmetic operators):基本的用于算术运算的运算符,比如加法和减法。

浮点数函数(Floating-point arithmetic functions):高级算术运算,包括对数和三角函数。

可变的整数函数(Mutable integer functions):用于处理可变整数的函数。

元组函数(Tuple functions)用于处理元组的函数。

转换函数(Conversion functions):用于在基本类型(primitive types)之间的转换,比如字符串、浮点数和整数。

 

 

算术运算符(Arithmetic Operators

 

正如我们在第二章中已经讨论的,F#的运算符能够由程序员定义,因此,所有的算术运算符都是在 Operators 模块中定义的,而不是语言所内置的。因此,我们日常使用 F# 编程的运算符大多数都是在 Operators模块中定义的。我们假设这些运算符,比如 + -,几乎不需要解释,因为它们的用法很简单:

 

let x1 = 1 + 1

let x2 = 1 – 1

 

默认情况下,F# 的运算符是不检查的,这样,如果一个值太大,那么有可能会绕回。因此,值有可能会变得很小,但并不引发错误。如果我们打算检查值溢出时,触发异常的运算符,需要引用 Microsoft.FSharp.Core.Operators.Checked

 

open Microsoft.FSharp.Core.Operators.Checked

let x = System.Int32.MaxValue + 1

 

现在,运行上面的示例就会出错,而如果没有引用 Microsoft.FSharp.Core.Operators.Checked,那么,x的值会直接绕回到 -2147483648

F# 的相等运算符与其大多数算术运算符相比,有一点微妙,这是因为 F#的相等是结构相等(structural equality),即对对象的内容进行比较,检查组成对象的每一项是否相等;它与引用相等(referential equality)相对,即确定两个标识符是否绑定到同一个对象,或者同一段物理内存空间。引用相等的检查通过执行 obj.ReferenceEquals方法;结构相等的运行符是等号(=),结构不等的运算符是 <>。下面的示例有所演示。记录 robert1 robert2相等,因为,它们虽然是不同对象,但它们的内容相同;而 robert1 robert3 不等,因为它们的内容不同。

 

type person = { name : string ; favoriteColor : string }

 

let robert1 = { name = "Robert" ; favoriteColor = "Red" }

let robert2 = { name = "Robert" ; favoriteColor = "Red" }

let robert3 = { name = "Robert" ; favoriteColor = "Green" }

 

printfn "(robert1 = robert2): %b" (robert1 = robert2)

printfn "(robert1 <> robert3): %b" (robert1 <> robert3)

 

代码的运行结果如下:

 

(robert1 = robert2): true

(robert1 <> robert3): true

 

结构比较(Structural comparison)使用大于(>)和小于(<)运算符实现,因此,它们也可以用来比较 F#的记录类型。下面是演示:

 

type person = { name : string ; favoriteColor : string }

 

let robert2 = { name = "Robert" ; favoriteColor = "Red" }

let robert3 = { name = "Robert" ; favoriteColor = "Green" }

 

printfn "(robert2 > robert3): %b" (robert2 > robert3)

 

代码的运行结果如下:

 

(robert2 > robert3): true

 

如果需要确定两个对象是否物理上相等,可以使用 PhysicalEquality函数,在 LanguagePrimitives 模块中,如下面的示例:

 

type person = { name : string ; favoriteColor : string }

 

let robert1 = { name = "Robert" ; favoriteColor = "Red" }

let robert2 = { name = "Robert" ; favoriteColor = "Red" }

 

printfn "(LanguagePrimitives.PhysicalEquality robert1 robert2): %b"

  (LanguagePrimitives.PhysicalEquality robert1 robert2)

 

 

浮点数函数(Floating-point arithmetic functions

 

Operators 模块还提供了大量的函数(见表 7-1),专门用于浮点数的运算,下面的示例是一些应用:

 

printfn "(sqrt 16.0): %f" (sqrt 16.0)

printfn "(log 160.0): %f" (log 160.0)

printfn "(cos 1.6): %f" (cos 1.6)

 

代码的运行结果如下:

 

(sqrt 16.0): 4.000000

(log 160.0): 5.075174

(cos 1.6): -0.029200

 

7-1 浮点数函数

函数

描述

abs

返回参数的绝对值

acos

返回参数的反余弦(arccosine),参数以弧度表示

asin

返回参数的反正弦(arcsine),参数以弧度表示

atan

返回参数的反正切(arctangent),参数以弧度表示

atan2

返回两个参数的反正切(arctangent),参数都以弧度表示

ceil

返回下一个最大的整数值,如果需要,值会舍入;返回值仍然是浮点数

floor

返回下一个最小的整数值,如果需要,值会舍入;返回值仍然是浮点数

exp

以自然常数 e 为底的指数函数

infinity

返回表示无穷大的浮点数

log

返回浮点数的自然对数

log10

返回浮点数的以 10 为底对数

nan

返回表示“不是数字”的浮点数

sqrt

返回平方根

cos

返回参数的余弦,参数以弧度表示

cosh

返回参数的双曲余弦,参数以弧度表示

sin

返回参数的正弦,参数以弧度表示

sinh

返回参数的双曲正弦,参数以弧度表示

tan

返回参数的正切,参数以弧度表示

tanh

返回参数的双曲正切,参数以弧度表示

truncate

返回参数的整数部分;返回值仍然是浮点数

float

返回整数的浮点(float)数

float32

返回整数的浮点(float32)数

 

 

元组函数(Tuple Functions

 

Operators 模块中还有两个有用的函数用于处理元组,函数 fst snd 把有两项的元组拆分并取出。下面的示例演示了其用法:

 

printfn "(fst (1, 2)): %i" (fst (1, 2))

printfn "(snd (1, 2)): %i" (snd (1, 2))

 

代码的运行结果如下:

 

(fst (1, 2)): 1

(snd (1, 2)): 2

 

 

转换函数(Conversion Functions

 

operator 模块还提供了大量的重载函数(overload function),用于在基本类型(primitive type)之间进行转换。例如,函数 float被重载,把字符串或整数转换成浮点数 System.Double。下面的示例演示了把一个枚举转换成整数,再把它转回枚举。把枚举转换成整数很简单,只要用 int函数就行了;把整数转回枚举有点复杂了,需要使用 enum 函数,还必须提供类型类型注解,使编译器能够知道所整数转换成哪一种枚举。可以看到,在下面的示例中,为标识符 dayEnum添加的注解 DayOfWeek

 

open System

 

let dayInt = int DateTime.Now.DayOfWeek

let (dayEnum : DayOfWeek) = enum dayInt

 

printfn "%i" dayInt

printfn "%A" dayEnum

 

代码的运行结果如下:

 

0

Sunday

 

 

逻辑与和或运算符

 

需要利用枚举执行的另一组任务,一是用逻辑或组合枚举,二是用逻辑与测试枚举。枚举类型用 System.Flags特征标记,支持使用 &&& |||运算符直接执行这两个运算。例如,可以使用 ||| 运算符组合几个枚举值;以 v1 &&& v2 <> enum 0形式使用 &&& 运算符,测试值是否是枚举的一部分:

 

open System.Windows.Forms

 

let anchor = AnchorStyles.Left ||| AnchorStyles.Left

 

printfn "test AnchorStyles.Left: %b"

  (anchor &&& AnchorStyles.Left <> enum 0)

printfn "test AnchorStyles.Right: %b"

  (anchor &&& AnchorStyles.Right <> enum 0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值