使用 F# 的 `ref` 与 `mutable` 赋值运算符

发布于 2024-12-10 12:14:39 字数 265 浏览 0 评论 0原文

考虑以下代码:

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. )

为什么引用赋值运算符 (:=) 与可变赋值运算符 (<-) 具有不同的行为?

Consider the following code:

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. )

Why does the ref assignment operator (:=) have a different behaviour than the mutable assignment operator (<-)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尘曦 2024-12-17 12:14:39

我只能给出部分答案。

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

I can only give a partial answer.

:= is defined in terms of <- in FSharp.Core\prim-types.fs:

let (:=) x y = x.contents <- y

In your example

b := // does not work
  printfn "%A" a
  4. + 8.

printfn "%A" a seems to be interpreted as y, which cannot be assigned to the int ref cell (wrong type). By grouping the whole expression with ( ... ), y now also contains 4. + 8.. Maybe the two operators behave differently, because <- seems to be an intrinsic operator (i.e. part of the language, not the library).

失而复得 2024-12-17 12:14:39

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

作业中允许更复杂的表达式,只要最终表达式是几种允许的形式之一。请参阅第 6.4.9 节规格的。这允许复杂的赋值,例如:

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

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

Building on the other answers...

More elaborate expressions are allowed within assignments, so long as the final expression is one of several allowed forms. See section 6.4.9 of the spec. This allows complex assignments such as:

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

The compiler moves gcd to a private member, but nesting it within the assignment allows for tighter scoping. Function arguments, on the other hand, are more restricted. They don't create a new scope (that I'm aware of) and you can't define functions, for example, as part of the expression.

盛夏已如深秋| 2024-12-17 12:14:39

:= 是一个函数(在 FSI 中尝试 (:=);;),其类型为: 'a ref -> '一-> unit

因此

b := // does not work
  printfn "%A" a
  4. + 8.

由于中缀调用解析规则,

(:=) b (printfn "%A" a)
4. + 8.

被解析为:与 (:=) 函数类型一样无效。
其他示例:

let c = 10 + 
            11 
            12

此处 c 为 12

:= is a function (try (:=);; in FSI) which has a type : 'a ref -> 'a -> unit

So

b := // does not work
  printfn "%A" a
  4. + 8.

is being parsed as because of the infix call parsing rule:

(:=) b (printfn "%A" a)
4. + 8.

Which is invalid as par the (:=) function type.
Other example:

let c = 10 + 
            11 
            12

c would be 12 here

无敌元气妹 2024-12-17 12:14:39

看起来像是缩进敏感解析器中的差异,而不是专门与这些运算符有关的任何内容。

Looks like a discrepancy in the indentation-sensitive parser rather than anything specifically to do with those operators.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文