请考虑以下代码:
let mutable a = 0.
let b = ref 0.
a <- // works
printfn "%A" a
4. + 8.
b := // does not work
printfn "%A" a
4. + 8.
b := ( // works
printfn "%A" a
4. + 8. )
为什么ref赋值运算符(:=)的行为与可变赋值运算符(&lt ;-)不同?
答案 0 :(得分:2)
我只能给出部分答案。
:=
是根据FSharp.Core \ prim-types.fs中的<-
定义的:
let (:=) x y = x.contents <- y
在你的例子中
b := // does not work
printfn "%A" a
4. + 8.
printfn "%A" a
似乎被解释为y
,无法将其分配给int ref单元格(错误类型)。通过将整个表达式分组为( ... )
,y
现在还包含4. + 8.
。也许两个运算符的行为不同,因为<-
似乎是一个内在的运算符(即语言的一部分,而不是库)。
答案 1 :(得分:1)
:=
是一个函数(try(= =);;在FSI中),其类型为:'a ref -> 'a -> unit
所以
b := // does not work
printfn "%A" a
4. + 8.
由于中缀调用解析规则,正在被解析:
(:=) b (printfn "%A" a)
4. + 8.
与(= =)函数类型相同无效。 其他例子:
let c = 10 +
11
12
c将是12在这里
答案 2 :(得分:1)
以其他答案为基础......
分配中允许使用更复杂的表达式,只要最终表达式是多个允许的表单之一即可。请参阅规范的section 6.4.9。这允许复杂的分配,例如:
let x =
let rec gcd a = function
| 0 -> a
| b -> gcd b (a % b)
gcd 10 25
编译器将gcd
移动到私有成员,但将其嵌套在赋值中允许更严格的作用域。另一方面,函数参数受到更多限制。它们不会创建一个新的范围(我知道)并且您无法定义函数,例如,作为表达式的一部分。
答案 3 :(得分:0)
看起来像是缩进敏感的解析器中的差异,而不是与这些运算符有关的任何内容。