Когда fact(3) вызвала fact(2), она не исчезла — она остановилась
недоделанной и ждала ответа. Этот урок о том, где ждут такие остановленные
вызовы и что можно сделать в момент, когда каждый из них просыпается.
У каждого вызова свой кадр
Вызов функции создаёт кадр: небольшой блок памяти с параметрами и локальными переменными этого вызова и местом, куда нужно вернуться, когда он закончится. Кадры складываются в стек вызовов — новый сверху, — и работает только верхний. Когда он возвращается, его кадр выбрасывается, а нижний продолжает ровно с того места, где остановился.
Отсюда два следствия:
- У каждого вызова своя копия переменных.
nвнутриfact(2)иnвнутриfact(3)— разные коробки, и изменение одной никогда не трогает другую. - Вызовы заканчиваются в обратном порядке: последний вызванный возвращается первым.
Работа на пути вниз и на пути обратно
Рекурсивный вызов делит функцию на две половины: код до вызова выполняется, пока вызовы уходят глубже, а код после — пока они возвращаются, в обратном порядке. Пройдите по шагам функцию, которая печатает в обоих местах: