3

考虑以下代码:

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 赋值运算符 (:=) 与可变赋值运算符 (<-) 的行为不同?

4

4 回答 4

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.。也许这两个运算符的行为不同,因为<-似乎是一个内在的运算符(即语言的一部分,而不是库)。

于 2011-10-18T09:31:36.547 回答
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

于 2011-10-18T09:36:20.917 回答
1

在其他答案的基础上...

只要最终表达式是几种允许的形式之一,就可以在赋值中使用更复杂的表达式。请参阅规范的第 6.4.9 节。这允许进行复杂的分配,例如:

let x =
  let rec gcd a = function
    | 0 -> a
    | b -> gcd b (a % b)
  gcd 10 25

编译器移动gcd到私有成员,但将其嵌套在赋值中允许更严格的范围。另一方面,函数参数受到更多限制。它们不会创建新的范围(我知道),并且您不能将函数定义为例如表达式的一部分。

于 2011-10-18T14:14:02.990 回答
0

看起来像是缩进敏感解析器中的差异,而不是与这些运算符特别有关的任何事情。

于 2013-09-20T23:07:47.640 回答