I'm more familiar with ocaml but it all looks the same to me.
val y=2;
fun f(x) = x*y;
The first two lines bind variables y
and f
. y
to an integer 2
and f
to a function which takes an integer x
and multiplies it by what's bound to y
, 2
. So you can think of the function f
takes some integer and multiplies it by 2
. (f(x) = x*2
)
fun g(h) = let val y=5
in
3+h(y)
end;
The next line defines a function g
which takes some h
(which turns out to be a function which takes an integer and returns an integer) and does the following:
- Binds the integer
5
to a temporary variable y
.
- You can think of the
let
/in
/end
syntax as a way to declare a temporary variable which could be used in the expression following in
. end
just ends the expression. (this is in contrast to ocaml where end
is omitted)
- Returns the sum of
3
plus the function h
applying the argument y
, or 5
.
At a high level, the function g
takes some function, applies 5
to that function and adds 3
to the result. (g(h) = 3+h(5)
)
At this point, three variables are bound in the environment: y = 2
, f = function
and g = function
.
let val y=3
in
g(f)
end;
Now 3
is bound to a temporary variable y
and calls function g
with the function f
as the argument. You need to remember that when a function is defined, it keeps it's environment along with it so the temporary binding of y
here has no affect on the functions g
and f
. Their behavior does not change.
g
(g(h) = 3+h(5)
), is called with argument f
(f(x) = x*2
). Performing the substitutions for parameter h
, g
becomes 3+((5)*2)
which evaluates to 13
.
I hope this is clear to you.