Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 错误FS0037有时非常混乱_F#_Functional Programming_Shadowing - Fatal编程技术网

F# 错误FS0037有时非常混乱

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的行为类似于可变),

如果我编写以下F#代码,编译器将发出一个错误

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中的工作方式