Функция может быть оптимизирована с помощью хвостового вызова, если она возвращает прямой вызов самому себе или не вызывает самого себя. Функция mylength-inner вернет либо x
, либо (mylength-inner (cdr s) (+ x 1))
, поэтому она может быть оптимизирована для хвоста.
Это означает, что компилятор может превратить его в цикл вместо рекурсивного вызова функции. Либо верните x, либо присвойте (cdr s) s, увеличьте x и начните снова сверху. (Стандарт Scheme требует, чтобы реализации могли выполнять эту оптимизацию, в то время как стандарт Common Lisp оставляет его на усмотрение реализации. Конечно, эта оптимизация очень полезна, поэтому большинство реализаций будут делать это.)
В неоптимизированной версии l не просто возвращает вызов l, а скорее результат вызова l с добавленным. Это означает, что он не может быть напрямую превращен в цикл, поэтому все вызовы функций должны быть выполнены.
Предположим, компилятор хотел превратить l в цикл. Нет проблем с присвоением (rest s) s, но куда он помещает (1 + ...)
?