F# 错误FS0037有时非常混乱
如果我编写以下F#代码,编译器将发出一个错误F# 错误FS0037有时非常混乱,f#,functional-programming,shadowing,F#,Functional Programming,Shadowing,如果我编写以下F#代码,编译器将发出一个错误 let a = 123 let a = 123 产生的错误是: 错误FS0037:值“a”的定义重复 如果我在这样的函数中编写相同的代码: let fctn = let a =123 let a =123 a 它不会产生任何错误 我不明白有什么区别。谁能解释一下吗 编辑:我在模块级编写的第一个代码。第一个代码定义了两个同名的公共值 第二个隐藏(阴影)值 对于第一种方法,您可以看到外部可见的状态变化(a的行为类似于可变),
let a = 123
let a = 123
产生的错误是:
错误FS0037:值“a”的定义重复
如果我在这样的函数中编写相同的代码:
let fctn =
let a =123
let a =123
a
它不会产生任何错误
我不明白有什么区别。谁能解释一下吗
编辑:我在模块级编写的第一个代码。第一个代码定义了两个同名的公共值 第二个隐藏(阴影)值 对于第一种方法,您可以看到外部可见的状态变化(
a
的行为类似于可变),而对于第二种方法,您不能看到外部可见的状态变化(在不同的范围内有两个a
s)
如果您使用#light off
ML语法编写语句,它会立即变得明显。关于范围和阴影
正如CaringDev所提到的(但没有解释),当你使作用域变得更明显时,你可能会看到阴影是关于什么的(使用让…进入…
构造#灯光
让你缩短一点-但是你仍然可以使用它,即使没有#灯光
)
试试这个:
> let a = 233 in let a = 555 in a;;
val it : int = 555
如您所见,表达式的计算结果为阴影值a
——但原始值并未丢失:
> let a = 233 in (let a = 555 in a), a;;
val it : int * int = (555, 233)
它只是不在内部的范围内,让。。。在…中
顺便说一句:您可以将示例改写为:
let fctn =
let a = 123 in
(let a =123 in a)
(我添加括号只是为了让这一点更加明显)
模块级别上的另一个定义了模块范围的值,实际上不是一个表达式,而是一个定义我同意这令人困惑。问题在于
let
在用作局部变量(在函数中)和用作全局定义(在模块中)时的行为不同
全局定义(在模块中)编译为静态类的静态成员,因此名称只能使用一次。这意味着顶级使用:
let a = 10
let a = 11
。。。是一个错误,因为F#必须生成两个同名的静态成员
局部定义(在函数或其他嵌套范围内)编译为IL,变量名基本上消失(IL使用堆栈)。在这种情况下,F#允许变量隐藏,您可以隐藏现有名称的变量。这可以在函数内部,甚至只是一个do
块:
do
let a = 10
let a = 11
()
这有点令人困惑,因为变量阴影只在局部范围内工作,而不在顶层工作。当你知道事情是如何编译的时候,这是有道理的。不清楚你在问什么。提供剪切并将其粘贴到fsi中会给两者带来本质上相同的错误。From:
在除模块作用域以外的任何作用域级别上,重用值或函数名都不是错误。如果重复使用名称,则后面声明的名称将与前面声明的名称形成阴影。但是,在模块的顶级作用域中,名称必须是唯一的。
是的,在我的手机上书写。。。计划稍后添加解释。谢谢,是的!!对你的答案非常满意。这不仅令人困惑,而且也不是它在OCaml中的工作方式