【问题标题】:Why does bigint compile in one case and not in the other?为什么 bigint 在一种情况下编译而不在另一种情况下编译?
【发布时间】:2017-02-09 00:28:08
【问题描述】:

我刚开始使用 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 *)

【问题讨论】:

  • 你为什么希望第二个工作?
  • 因为与第一个的唯一区别是括号。例如,let j = int "4";;let k = (int) "4";; 都工作并且具有相同的输出 val j : int = 4
  • @Soldalma: 'int' 实际上是 Core 库中定义的一个函数,它使用一些神秘的内联来找到正确的类型转换,因此它在使用括号时也有效。另请参阅github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/… 第 4262 行。

标签: f#


【解决方案1】:

那是因为过载。看,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

或者用另一种方式表达相同的想法:因为函数参数不在括号内,它不能用于计算括号内的表达式;并且因为没有参数,所以没有办法解决重载。

【讨论】:

  • 您明确指出了问题,但括号的作用仍不清楚。在这两种不起作用的情况下,都没有括号。为什么解析器/编译器不直接忽略或丢弃括号?
  • 更新了答案。
猜你喜欢
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
  • 2021-12-30
  • 2016-02-29
  • 1970-01-01
  • 2019-12-12
相关资源
最近更新 更多