我想创建一个名为result的全局变量,它使用5个字符串连接来创建一个包含字符串start的9倍的字符串,用逗号分隔。 我有两段代码,只有第二段代码声明了一个全局变量。 出于某种原因,它不能轻易地在我的脑中注册......难道只是因为我使用了一个let in,所以第一段代码的结果是一个局部变量?对此有更详细的解释吗?
let start = "ab";;
let result = start ^ "," in
let result = result ^ result in
let result = result ^ result in
let result = result ^ result in
let result = result ^ start in
result;;
- : string = "ab,ab,ab,ab,ab,ab,ab,ab,ab"
let result =
let result = start ^ "," in
let result = result ^ result in
let result = result ^ result in
let result = result ^ result in
let result = result ^ start in
result;;
val result : string = "ab,ab,ab,ab,ab,ab,ab,ab,ab"
答案 0 :(得分:5)
让我成为一个有点无聊的人。 OCaml中没有本地和全局变量。这个概念来自具有不同范围规则的语言。此外,应谨慎使用“变量”一词。其含义被类C语言所歪曲。这个词的原始数学意义对应于某个数学对象的名称,该名称在公式内使用,表示一系列此类值。在类C语言中,变量与内存单元混淆,后者可能会随时间变化。因此,为了避免混淆,让我们使用更准确的术语。让我们使用单词 name 而不是变量。因为,变量......抱歉名称不是内存单元格,所以没有什么可以创建的。当您使用let
语法之一时,实际上是在创建绑定,即名称和值之间的关联。 let <name> = <expr-1> in <expr-2>
绑定<expr-2>
表达式范围内的值。 let <name> = <expr-1> in <expr-2>
本身也是一个表达式,因此,例如<expr-2>
内部也可以包含let ... in ...
构造,例如,
let a = 1 in
let b = a + 1 in
let c = b + 1 in
a + b + c
我特别是,以非惯用方式缩进代码以突出表达式的句法结构。 OCaml还允许使用已在范围内绑定的名称。新绑定将隐藏现有绑定(例如,在C中不允许),例如,
let a = a + 1 in
let a = a + 1 in
let a = a + 1 in
a + a + a
最后,顶级(又称模块级别)let-binding(在OCaml用语中称为 definition )的语法为:let <name> = <expr>
,请注意没有{{1 }} 这里。该定义将in
绑定到词法范围中<name>
的评估结果,该范围从定义点延伸到封闭模块的末尾。在实现模块时,必须使用<expr>
将代码绑定到名称(可以使用let <name> = <expr>
省略名称)。它与交互式顶层(交互式_
程序)略有不同,它实际上接受一个表达式并对其进行求值。例如,
ocaml
不是有效的OCaml程序(可以放入let result = start ^ "," in
let result = result ^ result in
let result = result ^ result in
let result = result ^ result in
let result = result ^ start in
result
文件并编译的东西)。因为它是表达式,而不是模块定义。
答案 1 :(得分:1)
是不是只使用了
let in
所以第一段代码的结果是局部变量?
差不多。定义全局变量的语法是let variable = expression
,没有in
。定义局部变量的语法是let variable = expression in expression
,它将variable
之后的表达式定义为in
。
答案 2 :(得分:0)
当您let ... in
时,您将声明一个本地变量。如果您自己只有let
(在模块的顶层),那么您将声明模块的全局名称。 (即,可以从模块导出的名称。)
您的第一个示例完全由let ... in
组成。所以没有宣布顶级名称。
您的第二个示例本身有一个let
,后面有几次出现let ... in
。所以它声明了一个顶级名称result
。