在某些情况下,F# 记录行为对我来说很奇怪:
没有关于歧义的警告
type AnotherPerson = {Id: int; Name: string}
type Person = {Id: int; Name: string;}
// F# compiler will use second type without any complains or warnings
let p = {Id = 42; Name = "Foo";}
关于记录解构而不是记录构建的警告
F# 编译器在记录“解构”时发出警告,而不是在前一种情况下收到有关记录构造的警告:
// Using Person and AnotherPerson types and "p" from the previous example!
// We'll get a warning here: "The field labels and expected type of this
// record expression or pattern do not uniquely determine a corresponding record type"
let {Id = id; Name = name} = p
请注意,模式匹配没有警告(我怀疑这是因为模式是使用“记录构造表达式”而不是“记录解构表达式”构建的):
match p with
| {Id = _; Name = "Foo"} -> printfn "case 1"
| {Id = 42; Name = _} -> printfn "case 2"
| _ -> printfn "case 3"
缺少字段的类型推断错误
F# 编译器将选择第二种类型,然后会因为缺少 Age 字段而发出错误!
type AnotherPerson = {Id: int; Name: string}
type Person = {Id: int; Name: string; Age: int}
// Error: "No assignment given for field 'Age' of type 'Person'"
let p = {Id = 42; Name = "Foo";}
“记录解构”的丑陋语法
我问了我的几位同事一个问题:“这段代码是关于什么的?”
type Person = {Id: int; Name: string;}
let p = {Id = 42; Name = "Foo";}
// What will happend here?
let {Id = id; Name = name} = p
尽管“id”和“name”实际上是“左值”,但它们位于表达式的“右手边”,这让每个人都感到非常惊讶。我知道这更多地与个人喜好有关,但对于大多数人来说,在一种特定情况下,输出值放在表达式的右侧似乎很奇怪。
我不认为所有这些都是错误,我怀疑大多数这些东西实际上是功能。
我的问题是:这种晦涩的行为背后是否有任何理性?