Ключевым моментом для понимания является то, что эта строка:
h = mh(h)
Вызывает ли функцию h
. Он вызывает функцию mh()
, которая просто возвращает значение функции, но также не вызывает h()
. Если будет возвращено значение функции, это вызовет h()
.
Таким образом, функция main()
сохраняет значение функции в h
, а затем вызывает h()
.
Этот h()
печатает "before"
, затем переносит h
в другую функцию и сохраняет результат в h
, затем печатает "after"
. Важно знать, что функция-обертка (значение, возвращаемое mh()
) является замыканием и хранит исходное значение h
, поэтому присвоение результата h
не влияет на h
внутри обернутого функция.
Итак, h
заканчивается вызовом h
, который теперь является упакованной функцией. Обернутая функция начинается с печати "return"
, затем она вызывает оригинал, развернутый h
.
Оригинал, развернутый h
, снова печатает "before"
, затем переносит текущее значение h
(которое является функцией переноса), сохраняет его в h
, затем печатает "after"
.
И затем вызывает h
, который теперь представляет собой двойную упакованную функцию. Он начинается с печати "return"
, а затем вызывает сохраненное значение h
, которое является однократной упакованной функцией. Функция однократного переноса начинается с печати "return"
(снова), затем продолжается с исходной, которая печатает "before"
, переносит h
, который теперь будет переноситься 3 раза, сохраняет ее в h
, затем вызывает h
(что является значением функции с 3-кратным переносом) ...
Эта логика продолжается, значение функции, хранящееся в h
, будет упаковываться все больше и больше, а функция с переносом всегда будет иметь сохраненное значение однократного переноса предыдущей функции.
По мере продолжения «итерации» «глубина переноса» увеличивается, поэтому вы увидите все больше и больше напечатанных операторов "return"
(как и делает перенос).