Нет. Только потому, что функциональная функция реализована с императивным кодом за кулисами, это не делает функцию обязательной. Наши вычислительные машины являются обязательными; поэтому в какой-то момент весь функциональный код должен быть реализован путем перевода в императивный код!
Ключевым моментом для понимания является следующее: функциональное программирование относится к интерфейсу , а не к реализации . Кусок кода работает, если сам этот код не может наблюдать каких-либо побочных эффектов, даже если побочные эффекты действительно происходят за кулисами. То есть, если вы проверяете значение одной и той же привязки одной и той же переменной несколько раз, вы получите одно и то же значение, даже если это значение, закулисное, было помещено туда с использованием set!
.
В случае letrec
здесь есть небольшой улов: результат не определен, если оценка любого из привязок в letrec
вызывает отмену защиты другого. Итак, результат этого кода не определен:
(letrec ((foo bar)
(bar 7))
(cons foo bar))
Значение foo
в теле letrec не определено. С другой стороны, определяется результат следующего:
(letrec ((foo (lambda () bar))
(bar 7))
(cons (foo) bar))
Это потому, что оценка lambda
фиксирует ссылку на бар, но фактическое значение не ищется, пока в теле не будет выполнено замыкание.