Почему в Ocaml такое неочевидное поведение вложенных блоков?
Например:
let println x = print_int x ; print_newline ()
let proc0a () =
print_endline "proc0a" ;
let x = 1
in
println x ;
let x = 2
in
println x ;
println x
let proc0b () =
print_endline "proc0b" ;
let x = 1
in begin
println x ;
let x = 2
in begin
println x
end ;
println x
end
let proc0c () =
print_endline "proc0c" ;
let x = 1
in (
println x ;
let x = 2
in (
println x
) ;
println x
)
let proc1 () =
print_endline "proc1" ;
let x = 1
in
println x ;
( let x = 2
in
println x
) ;
println x
let proc p =
p () ;
print_newline ()
let _ = List.iter proc [ proc0a; proc0b; proc0c; proc1 ]
получаем:
proc0a
1
2
2
proc0b
1
2
2
proc0c
1
2
2
proc1
1
2
1
Я ожидал от proc0(a|b|c) поведения аналогичного proc1, но нет.
В SML поведение соответствует ожиданиям:
fun println x = print (Int.toString x ^ "\n")
fun proc0 () = (
print "proc0\n" ;
let val x = 1
in
println x ;
let val x = 2
in
println x
end ;
println x
end
)
val _ = proc0 ()
=>
proc0c
1
2
1
Как и в Haskell:
proc0a = do
putStrLn "proc0a"
let x = 1 in do
print x
let x = 2 in do
print x
print x
proc0b = do {
putStrLn "proc0b" ;
let x = 1 in do {
print x ;
let x = 2 in do {
print x
} ;
print x
}
}
proc1a = do
putStrLn "proc1a"
let x = 1 in do
print x
let x = 2 in do
print x
print x
proc1b = do {
putStrLn "proc1b" ;
let x = 1 in do {
print x ;
let x = 2 in do {
print x ;
print x
}
}
}
main = mapM_ (\p -> p >> putStrLn "") [ proc0a, proc0b, proc1a, proc1b ]
=>
proc0a
1
2
1
proc0b
1
2
1
proc1a
1
2
2
proc1b
1
2
2
Как и в любом другом языке (может, в F#, как, во-многом, наследнике Ocaml, поведение аналогично предку? Лень проверять).
Так почему разработчики Ocaml сделали так, а не как у людей?