Я только что наткнулся на интересный пример рекурсивных лямбд, и я не очень понимаю, почему это работает таким образом.
rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec
rec = lambda x: x+1
print(f(10))
То же в JavaScript.
var rec = function(a) {
if (a == 0) return 1;
return rec(a - 1) * a;
}
var f = rec
rec = function(a) {
return a + 1;
}
console.log(f(10));
К моему удивлению, оба из этих отпечатков 100 вместо 10! (как я и ожидал).
Почему переназначение rec меняет поведение функции f? Когда переменная rec записывается в лямбду, не относится ли она к самой лямбде?
Редактировать.
Поскольку большинство ответов объясняют, что происходит, позвольте мне перефразировать вопрос, потому что я ищу более подробное объяснение.
Итак, в момент объявления функции rec в первой строке, почему rec в теле функции не привязывается к себе?
Например, если вы берете JavaScript и переписываете первую строку, по-видимому, «так же», как предложено в одном из полученных ответов:
var rec =function rec(a) {
if (a == 0) return 1;
return rec(a - 1) * a;
};
f = rec;
rec = function (a) {
return a + 1;
}
console.log(f(10));
Этот выводит 10! как и следовало ожидать.
Таким образом, в этом случае «внутренняя запись» (в теле функции) связывается с записью имени функции вместо того, чтобы смотреть на переменную записи, и переназначение переменной записи не изменило поведение.
Так что я действительно спрашиваю, это механизм, с помощью которого эти языки решают, что связывать переменные в лямбдах.
Я сам пишу переводчик для проекта класса, и я столкнулся с тем же вопросом, когда и где связывать эти переменные. Поэтому я хотел понять, как это работает на популярных языках, чтобы реализовать нечто подобное.