For this question, let's say that there are three things that can make you actually value the value:
- Pattern matching for this value
- Applying a Value to an Argument
- Using it as the first argument to
seq
The actual situation is a little more complicated, but not so important.
In addition, this coercion occurs only in the context of any external expression, therefore, instead of thinking of it as a โforced evaluationโ in some abstract way, it helps to think of them as an evaluation of an external expression, depending on the evaluation of this values. That is why, for example, seq xx in any sense does not force x , since this is the final value of the expression anyway; he says that when evaluating an external expression (whose value is x ), it must also evaluate x , which is redundant.
Finally, any value that depends on the forced value of undefined is itself undefined.
Passing each expression:
seq undef1 () = undefined
In this case, undef1 is undefined, and seq undef1 x is an expression whose value is x and depends on the evaluation of undef1 . Thus, the expression as a whole is undefined, regardless of what the second argument to seq .
seq undef2 () = ()
In this case, undef2 not undefined, but the result of its application. seq undef2 x is an expression whose value is x and depends on the evaluation of undef2 . This is not a problem, and the first argument to seq discarded, so the value of expression () here.
undef2 () = undefined
In this case, we directly apply undef2 . The expression undef2 () depends on the evaluation of undef2 (this is good) and is evaluated with the result of applying undef2 , which in this case is undefined .
Compare this to the fourth case:
undef1 () = undefined
In this case, we use undef1 , so the value of the expression depends on the evaluation of undef1 , which is undefined, and therefore the whole expression is the same. This is the same value as the previous expression using undef2 , but for a completely different reason!