记录是一组字段的集合,这些字段可以有不同的类型,但彼此关联。定义记录要使用 type关键字。记录的字段定义在{和}之间,每个字段都有一个名称_和_一个类型。创建记录时,要在{和}之间写出各字段的名称并为它们赋值。创建记录时必须为所有字段赋值。可以用点号表示法访问记录实例的字段值。
定义或创建记录时,每个字段要么单独占一行,要么写在同一行并用分号(;)分隔。
// Define a record
type Address =
{ Street: string
HouseNumber: int }
// Create a record
let oldAddress: Address =
{ Street = "Main Street"
HouseNumber = 17 }
// Single-line alternative
type ConciseAddress = { Street: string; HouseNumber: int }
let conciseAddress: ConciseAddress = { Street = "Main Street"; HouseNumber = 17 }
记录是不可变的,因此记录一旦构造完成,它的字段值就永远不会改变。如果你想修改记录的值,可以用 with关键字创建现有记录的副本,同时为一个或多个字段指定新的值。
// Copy the old address but change the house number
let newAddress: Address = { oldAddress with HouseNumber = 86 }
newAddress.Street // => "Main Street"
newAddress.HouseNumber // => 86
记录具有_结构相等_,也就是说,同一个记录的两个实例只要值完全相同,就彼此等价。
除了可以用点号表示法访问记录的字段之外,记录还可以在绑定和模式匹配中被_解构_:
let myAddress: Address = { Street = "Broadway"; HouseNumber = 123 }
let { Street = myStreet; HouseNumber = myHouseNumber } = myAddress
match myAddress with
| { HouseNumber = 1 } -> printfn "First house"
| { HouseNumber = houseNumber; Street = street } -> printfn "House number %d on %s" houseNumber street
// => "House number 123 on Broadway
在这个练习里,你是个超级体育迷,最近刚刚迷上了 NBA 篮球。由于刚接触 NBA 篮球,你正深入研究 NBA 的历史,记录各支球队、教练以及他们的胜负数据,并把它们相互比较。
你还没有最喜欢的球队,所以还要开发一个算法,来判断该不该支持某支球队。
你有 7 个任务,帮你打磨出属于你自己的_支持球队_算法。
定义Coach记录,它包含以下 2 个字段:
Name:教练的姓名,类型为string。FormerPlayer:表示教练是否为前球员,类型为bool。定义Stats记录,它包含以下 2 个字段:
Wins:胜场数,类型为int。Losses:负场数,类型为int。定义Team记录,它包含以下 3 个字段:
Name:球队名称,类型为string。Coach:球队的教练,类型为Coach。Stats:球队的数据,类型为Stats。实现createCoach函数,它接收教练姓名和其是否为前球员作为形参,并返回对应的Coach记录:
createCoach "Larry Bird" true
// => { Name = "Larry Bird"; FormerPlayer = true }
实现createStats函数,它接收胜场数和负场数作为形参,并返回对应的Stats记录:
createStats 58 24
// => { Wins = 58; Losses = 24 }
实现createTeam函数,它接收球队名称、教练和记录作为形参,并返回对应的Team记录:
let coach = createCoach "Larry Bird" true
let record = createStats 58 24
createTeam "Indiana Pacers" coach record
// => { Name = "Indiana Pacers"
// Coach = { Name = "Larry Bird"; FormerPlayer = true }
// Stats = { Wins = 58; Losses = 24 } }
NBA 的球队老板都没什么耐心,你发现战绩不佳往往会让教练被换掉。实现replaceCoach函数,它接收球队和新教练作为形参,并返回换上这位新教练后的球队:
let coach = createCoach "Larry Bird" true
let record = createStats 58 24
let team = createTeam "Indiana Pacers" coach record
let newCoach = createCoach "Isiah Thomas" true
replaceCoach team newCoach
// => { Name = "Indiana Pacers"
// Coach = { Name = "Isiah Thomas"; FormerPlayer = true }
// Stats = { Wins = 58; Losses = 24 } }
在钻研各种数据时,你会把球队和它们的记录整理成列表。有时你会弄错,列表里就出现了重复的条目。实现isSameTeam函数,它接收 2 支球队,如果它们是同一支球队就返回true;否则返回false:
let pacersCoach = createCoach "Larry Bird" true
let pacersStats = createStats 58 24
let pacersTeam = createTeam "Indiana Pacers" pacersCoach pacersStats
let lakersCoach = createCoach "Del Harris" false
let lakersStats = createStats 61 21
let lakersTeam = createTeam "LA Lakers" lakersCoach lakersStats
isSameTeam pacersTeam lakersTeam
// => false
看过许多球队和比赛之后,你想出了一个算法。只要满足下面任意一条,你就支持这支球队:
实现rootForTeam函数,它接收一支球队,如果你应该支持这支球队就返回true;否则就return false:
let spursCoach = createCoach "Gregg Popovich" false
let spursStats = createStats 56 26
let spursTeam = createTeam "San Antonio Spurs" spursCoach spursStats
rootForTeam spursTeam
// => true