为什么我要使用'let'而不仅仅是'val'来声明SML中函数内部的变量?

为什么我要使用'let'而不仅仅是'val'来声明SML中函数内部的变量?,sml,Sml,在SML中,我学到了将函数的局部变量定义为: fun correct_fun() = let val x = 1 in x + 2 end 为什么我必须使用let,而不是像这样使用val: fun incorrect_fun() = val x = 1 x + 2 不正确的\u fun()抛出了一个错误,但我不明白为什么。如果没有let,为什么不能在函数中使用val 为什么val不能在没有let的函数中使用 因为val是一种声明,let是一种表达式,函

在SML中,我学到了将函数的局部变量定义为:

fun correct_fun() =
    let val x = 1
    in x + 2
    end
为什么我必须使用
let
,而不是像这样使用
val

fun incorrect_fun() =
    val x = 1
    x + 2
不正确的\u fun()
抛出了一个错误,但我不明白为什么。如果没有
let
,为什么不能在函数中使用val

为什么
val
不能在没有
let
的函数中使用

因为
val
是一种声明,
let
是一种表达式,函数体是一种表达式

let
-表达式的语法结构是
let
dec
in
exp
end
。因此,在使用
let
-表达式作为函数体时,
let
中的
exp
相当于函数体,但具有扩展的局部范围,包括
dec
添加的内容

let
-表达式允许您使用任何类型的声明,而不仅仅是
val
声明

例如,您可以使用异常处理作为用于回溯的控制流机制,并且可以嵌套仅在本地使用并且可能采用多个参数来存储临时结果的帮助器函数,但您可能不希望公开异常或帮助器函数。因此,您可以对以下内容进行改进(摘自Niels Andersen关于函数式编程的补充说明,第140-143页):

展示它

- print (show (queen ((8,8))));
. . . . * . . . 
. . . . . . * . 
. * . . . . . . 
. . . . . * . . 
. . * . . . . . 
* . . . . . . . 
. . . * . . . . 
. . . . . . . * 

当你使用<代码>让-表达式主要声明临时值时,你也可以考虑用<代码> > < /COD>。关于这一点,请参见问答

为什么
val
不能在没有
let
的函数中使用

因为
val
是一种声明,
let
是一种表达式,函数体是一种表达式

let
-表达式的语法结构是
let
dec
in
exp
end
。因此,在使用
let
-表达式作为函数体时,
let
中的
exp
相当于函数体,但具有扩展的局部范围,包括
dec
添加的内容

let
-表达式允许您使用任何类型的声明,而不仅仅是
val
声明

例如,您可以使用异常处理作为用于回溯的控制流机制,并且可以嵌套仅在本地使用并且可能采用多个参数来存储临时结果的帮助器函数,但您可能不希望公开异常或帮助器函数。因此,您可以对以下内容进行改进(摘自Niels Andersen关于函数式编程的补充说明,第140-143页):

展示它

- print (show (queen ((8,8))));
. . . . * . . . 
. . . . . . * . 
. * . . . . . . 
. . . . . * . . 
. . * . . . . . 
* . . . . . . . 
. . . * . . . . 
. . . . . . . * 

当你使用<代码>让-表达式主要声明临时值时,你也可以考虑用<代码> > < /COD>。请参见Q&A以了解和了解这一点。

因此
val
不能在函数体中使用,因为函数体必须是表达式?另一方面,使用
val
“外部”(即在脚本中写入
val x=1
时)是可以的,因为“外部”允许声明?(这些东西听起来像是我不知道的函数编程的基础!)@Heisenberg:当你说的“函数外”是指函数声明之前或之后(例如,在顶层,或者在
let
-表达式的第一部分,或者其他一些地方),那么是的,你可以在那里有各种声明。这不是函数式编程的属性,而是标准ML语法的属性。在函数式编程的理论基础中,只有lambda表达式,没有任何类型的声明。因此
val
不能在函数体中使用,因为函数体必须是表达式?另一方面,使用
val
“外部”(即在脚本中写入
val x=1
时)是可以的,因为“外部”允许声明?(这些东西听起来像是我不知道的函数编程的基础!)@Heisenberg:当你说的“函数外”是指函数声明之前或之后(例如,在顶层,或者在
let
-表达式的第一部分,或者其他一些地方),那么是的,你可以在那里有各种声明。这不是函数式编程的特性,而是标准ML语法的特性。在函数式编程的理论基础中,只有lambda表达式,没有任何类型的声明。