gpt4 book ai didi

.net - 为什么在 F# 的一个方法中可以有多个 let 绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 15:07:38 24 4
gpt4 key购买 nike

一位同事查看了我的代码并问我为什么使用以下模式:

type MyType() =
member this.TestMethod() =
let a = 1
// do some work
let a = 2 // another value of a from the work result
()

我告诉他这是一个糟糕的模式,我的意图是使用 let mutable a = ... .但随后他问为什么在 F# 类中可能有这样的顺序绑定(bind),而在模块或 .fsx 中是不可能的。文件?实际上,我们正在改变一个不可变的值!

我回答说,在模块或 .fsx 文件中,let 绑定(bind)成为静态方法,因此同名的绑定(bind)会以与同名的两个类属性相同的方式发生冲突,这很简单。但我不知道为什么这在方法中是可能的!

在 C# 中,我发现范围变量很有用,尤其是在单元测试中,当我想通过复制粘贴代码片段来为测试用例组成一些不同的值时:
{
var a = 1;
Assert.IsTrue(a < 2);
}

{
var a = 42;
Assert.AreEqual(42, a);
}

在 F# 中,我们不仅可以重复相同的 let 绑定(bind),还可以将不可变的绑定(bind)更改为可变的绑定(bind),然后以通常的方式对其进行修改:
type MyType() =
member this.TestMethod() =
let a = 1
// do some work
let a = 2 // another value of a from the work result
let mutable a = 3
a <- 4
()

为什么我们可以在 F# 方法中重复 let 绑定(bind)?我应该如何向刚接触 F# 并询问“什么是不可变变量以及我为什么要对其进行变异”的人解释这一点?

就个人而言,我感兴趣的是为了实现这一点而做出了哪些设计选择和权衡?我对容易检测到不同范围的情况感到满意,例如当变量在构造函数中,然后我们在主体中重新定义它,或者当我们在 for 中定义新绑定(bind)时/ while循环。但是同一级别的两个连续绑定(bind)有点违反直觉。感觉我应该在心里加上 in到每一行的末尾,如在详细语法中解释范围,以便那些虚拟的 in s 类似于 C# 的 {}

最佳答案

我认为重要的是要解释 F# 中发生的事情与 C# 中发生的事情不同。变量阴影不是替换符号——它只是定义一个恰好与现有符号同名的新符号,这使得无法访问旧符号。

当我向人们解释这一点时,我通常会使用这样的示例 - 假设我们有一段代码使用 C# 中的变异进行一些计算:

var message = "Hello";
message = message + " world";
message = message + "!";

这很好,因为我们可以逐步构建消息。现在,我们如何在没有突变的情况下做到这一点?诀窍是在每一步定义新变量:
let message1 = "Hello";
let message2 = message1 + " world";
let message3 = message2 + "!";

这行得通——但我们并不真正需要我们在构建过程中定义的临时状态。因此,在 F# 中,您可以使用变量阴影来隐藏您不再关心的状态:
let message = "Hello";
let message = message + " world";
let message = message + "!";

现在,这意味着完全相同的东西——你可以很好地向使用 Visual F# Power Tools 的人展示它,它会突出显示所有出现的符号——所以你会看到这些符号是不同的(即使它们具有相同的名称) .

关于.net - 为什么在 F# 的一个方法中可以有多个 let 绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32051233/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com