为什么不能在没有let 的函数内部使用val?
因为val是一种声明,let是一种表达式,函数体是一种表达式。
let-表达式的句法结构是letdecinexpend。因此,在使用let-表达式作为函数体时,let 中的 exp 等效于函数体,但具有扩展的本地范围,无论 @ 987654339@ 补充道。
let-表达式允许您使用任何类型的声明,而不仅仅是 val 声明。
例如,您可以将异常处理用作用于回溯的控制流机制,并且您可以嵌套仅在本地使用并且可能需要多个参数来存储临时结果的辅助函数,但您可能不想公开异常或辅助函数。因此,对于Eight Queens puzzle,您可以改进this solution(来自关于函数式编程的补充说明,pp. 140-143,作者 Niels Andersen):
fun concatMap f xs = String.concat (List.map f xs)
fun concatTab f n = String.concat (List.tabulate (n, f))
fun dots n = concatTab (fn _ => ". ") n
fun show ys = concatMap (fn y => dots (y - 1) ^ "* " ^ dots (8 - y) ^ "\n") ys
fun queen dims =
let exception Queen
fun beats ((x,y),(x1,y1)) = (* x = x1 *)
(* orelse *) y = y1
orelse x + y = x1 + y1
orelse x - y = x1 - y1
fun safe ((x, y), _, []) = true
| safe ((x, y), x1, y1::ys) =
not (beats ((x, y), (x1, y1))) andalso safe ((x, y), x1 + 1, ys)
fun queen' ((0, _), ys) = ys
| queen' ((_, 0), _) = raise Queen
| queen' ((x, y), ys) =
if safe ((x, y), x + 1, ys)
then queen' ((x - 1, 8), y :: ys)
handle Queen => queen' ((x, y - 1), ys)
else queen' ((x, y - 1), ys)
in queen' (dims, []) end
展示它;
- print (show (queen ((8,8))));
. . . . * . . .
. . . . . . * .
. * . . . . . .
. . . . . * . .
. . * . . . . .
* . . . . . . .
. . . * . . . .
. . . . . . . *
当您使用let-表达式主要声明临时值时,您还可以考虑使用case-of。请参阅Difference between "local" and "let" in SML 和nested local declarations in ML of NJ 的问答。