Почему нельзя val
использовать внутри функции без let
?
Поскольку val
является своего рода объявлением, let
является разновидностью выражения, а тело функции является выражением.
Синтаксическая структура let
-экспрессии: let
dec
in
exp
end
. Таким образом, при использовании let
-выражения в качестве тела функции exp
в пределах let
эквивалентно телу функции, но с расширенной локальной областью независимо от того, dec
добавляет.
Выражение let
позволяет использовать любые объявления, а не только val
объявления.
Например, вы можете использовать обработку исключений в качестве механизма потока управления, используемого для обратного отслеживания, и вы можете вкладывать вспомогательные функции, которые используются только локально и, возможно, принимают несколько аргументов для хранения временного результата, но вы можете не захотеть выставлять исключение или вспомогательные функции. Так что для головоломки Восемь королев вы можете уточнить это решение (из дополнительных примечаний по функциональному программированию, с. 140-143 , Нильс Андерсен):
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
. См. Вопросы и ответы по Разница между "local" и "let" в вложенных локальных объявлениях SML и в ML для NJ .