To learn how defer and evaluations work, first let's look at the Spec: defer statements:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
Both the function value (whose call is deferred) and its parameters are evaluated. But the deferred function is not yet called.
Let's iterate toward your example with small steps:
defer f("a")
In this case the function value is evaluated (which will be f
), and the parameters are evaluated, which is a constant, so that's gonna be "a"
.
Next step:
defer f(g("a"))
In this case the function value is evaluated (which will be f
), and the parameters are evaluated, which means g
will be called with "a"
(because g
's return value is the param to f
).
Next step:
defer f()()
This is valid if the f
function returns a function. The function value will be evaluated (which means f
will be called!) but its return value will not be called, that is what will be deferred.
defer f(g())()
In this case the deferred function is the return value of f
, so to evaluate the deferred function value, f
must be called, and to do that g
must be called prior. The return value of f
will be deferred (not called).
Back to your example:
defer def("defered line")()
The function value is evaluated, which is the return value of def
, so def
is called. The return value of def
will be deferred. Its parameters are evaluated, but actually it has no parameters.
So logically this is what happens:
- The deferred function value is evaluated, which requires that:
def
function must be called, which requires that:
- Params to
def
are evaluated, it's a constant: "defered line"
- Parameters to the deferred function are evaluated; since there are no params to it, this step is done.
This is what happens sequentially if we lay out the above structure:
- Param to
def
is evaluated: it's a constant "defered line"
def
is called which prints tier up
and its argument: defered line
- The return value of
def
is not called, that is what's deferred.
- Function
main
prints: main
- Function
main
returns, so deferred functions are called now. The deferred function prints clean up