我刚刚开始使用F#,我发现下面显示的行为令人费解。有什么解释吗?
let bg = bigint 1;;
(* val bg : System.Numerics.BigInteger = 1 *)
let bg = (bigint) 1;;
(* error FS0041: A unique overload for method 'BigInteger' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.Numerics.BigInteger(value: byte []) : unit, System.Numerics.BigInteger(value: decimal) : unit, System.Numerics.BigInteger(value: float) : unit, System.Numerics.BigInteger(value: float32) : unit, System.Numerics.BigInteger(value: int) : unit, System.Numerics.BigInteger(value: int64) : unit, System.Numerics.BigInteger(value: uint32) : unit, System.Numerics.BigInteger(value: uint64) : unit *)
答案 0 :(得分:6)
那是因为超载。请注意,bigint
实际上是BigInteger
类的同义词,并且像函数一样应用它转换为调用构造函数,但是几个构造函数中的哪一个取决于参数的类型。
当你像函数一样应用它时,这很好用:参数的类型是已知的,编译器可以选择适当的重载。但是,如果您尝试将其视为函数值,则该参数不存在,并且编译器不知道要执行哪个重载。
这是一个更简单的复制品:
type T() =
member static f (s: string) = s
member static f (i: int) = I
let a = T.f 1 // works
let b = T.f "abc" // works
let c = T.f // doesn't work: which `f` do you mean?
// possible workaround: create non-overloaded wrappers
let fStr (s: string) = T.f s
let fInt (i: int) = T.f i
let a = fStr // works fine
let b = fInt // works fine, too
结论:重载很糟糕,不要使用它。但如果你坚持使用它,就把它搞定吧。或者使用解决方法。
(回应评论)
括号告诉编译器:“首先,在括号内计算这个表达式,然后取结果并用它做其余的”。因此,在括号中加上一个东西在语义上等同于给它一个名字,例如:
// Original repro:
let a = (bigint) 5
// Same thing:
let f = bigint
let a = f 5
或者说出同一个想法的另一种方式:因为括号内不存在函数参数,所以它不能用于计算括号内的表达式;并且由于没有参数,因此无法解决过载问题。