SML函数内为何需用let声明局部变量而非直接用val?
let for local variables in SML functions? Great question! This comes down to how SML's syntax and core concepts of declarations vs expressions work. Let's unpack this:
1. SML distinguishes between declarations and expressions
First, it's key to understand that SML has two distinct kinds of constructs:
- Declarations: Things like
val x = 1are declarations. Their job is to bind a name to a value, but they don't produce a value themselves. They're statements that modify the environment (the set of available names), but they aren't "evaluated" to return something. - Expressions: Constructs like
x + 2,3, orlet ... in ... endare expressions. When evaluated, they compute a value that can be used as part of other code (like a function's return value).
2. A function's body must be an expression
In SML, when you define a function with fun, the part after the = must be a single expression—this is what the function will evaluate and return when called.
Your incorrect example:
fun incorrect_fun() = val x = 1 x + 2
Here, you're trying to put a declaration (val x = 1) followed by an expression (x + 2) directly as the function body. But SML's parser expects an expression here, not a declaration. That's why you get a syntax error.
3. let turns declarations into a valid expression
The let ... in ... end construct is exactly the solution here. It's an expression that lets you:
- Write one or more declarations inside the
letblock (to create local bindings likeval x = 1), - Then specify an expression after
inthat uses those bindings, - Finally, the entire
letexpression evaluates to the value of thein-side expression.
Your correct example:
fun correct_fun() = let val x = 1 in x + 2 end
Here, the entire let ... end is a single expression that evaluates to 3—perfect for the function's body. Plus, the binding x = 1 is local to the let block—it doesn't exist outside of it, which prevents name collisions and keeps your function's internals encapsulated.
4. Why not just use val without let?
Simply put: you can't, because val is a declaration, not an expression. There's no way to use a standalone val declaration where an expression is required (like a function body). let is the idiomatic way in SML to package local declarations into a usable expression that fits the function's syntax requirements.
内容的提问来源于stack exchange,提问作者Heisenberg

