Innermost
evaluation :
Under
the innermost-evaluation rule, the evaluation of a function application
<name><actual-parameter>
proceeds
as follows :
--
Evaluate the expression represented by <actual-parameter>.
--
Substitute the result for the formal in the function body.
--
Evaluate the body.
--
Return its value as the answer.
Each
evaluation of a function body is called an activation of the function.
The
approach of evaluating arguments before the function body is also referred to
as call-by-value evaluation. Call-by-value can be implemented efficiently, so
it is widely used.
Under
call-by-value, all arguments are evaluated, whether their values are needed or
not.
Outermost
evaluation
:
Under
the outermost-evaluation rule, the evaluation of a function application
<name><actual-parameter>
proceeds
as follows :
--
substitute the actual (without evaluating it) for the formal in the function
body.
--
Evaluating the body.
--
Return its value as the answer.
Innermost
and outermost evaluation produce the same result if both terminate with a
result.
The
distinguishing difference between the evaluation methods is that actual
parameters are evaluated as they are needed in outermost evaluation; they are
not evaluated before substitution.
Standard
ML uses call-by-value or innermost evaluation.
Short-circuit
evaluation :
The operation andalso and orelse
in ML perform short-circuit evaluation of boolean expressions, in which the
right operand is evaluated only if it has to be.
E andalso
F is false if E is false; it is true if both E and F are true. The evaluation
of E andalso F proceeds from left to right, with F being evaluated only
if E is true.
So,
E andalso F may terminate even if F does not.
The
evaluation of E orelse F is true if E evaluates to be true. F is skipped
if E is true.
The
91-function :
fun f(x) =
if x > 100 then x - 10 else
f(f(x+11)) ;
f(100)
= if 100 > 100 then 100 - 10 else f(f(100+11))
= f(f(100+11)
= f(f(111))
= f( if 111 > 100 then 111 -10 else f(f(111+11))
= f(101)
= if 101 > 100 then 101 - 10
else f(f(101+11))
= 101 - 10
= 91
Outermost
evaluation :
f(100) = if 100 > 100 then 100 - 10
else f(f(100+11))
= f(f(100+11))
= if f(100+11) > 100 then
f(100+11) - 10 else f(f(f(100+11)))
.......
Outermost
vs innermost evaluation :
Outermost appears to do more work
than innermost.
Outermost
can
terminate where innermost fails .
fun
or(x,y) =
if x then true else y ;
--
under innermost-evaluation , both subexpression E and F are evaluated before
they are substituted into the function body. So, or(true,F) results in a
nonterminating computation if the evaluation of F does not terminate.
--
Under outermost -evaluation,
or(true,F) = if true then true else
F ;
so the computation terminates regardless of
the evaluation of F terminates or not.
Since
ML uses innermost evaluation, the operator orelse has to be provided by
the language. It cannot be user-defined as part of a program.
VAL
BINDINGS
:
The
occurrence of x to the right of the keyword val in
let val x = E1 in E2 end
is
called a binding occurrence or simply binding of x.
All
occurrences of x in E2 are said to be within the scope of this
binding.
The
occurrences of x within the scope of a binding are said to be bound.
A
binding of a name is said to be visible to all occurrences of the name in the
scope of the binding.
Eg.
let val x = 2 in let val x = x + 1 in x * x end
end
The
value of an expression is left undisturbed if we replace all occurrences of a
variable x within the scope of a binding of x by a fresh variable :
let val x = 2 in
let val y = x + 1 in y * y end end
let
fun f(x) = E1 in E2 end
The occurrences of f and x to the right of
keyword fun are bindings of f and x.
let x =
2 in
let fun f(x) = x + 1 in f(x) end end