The basic idea behind a named let
is that it allows you to create an internal function, that can call itself, and invoke it automatically. So your code is equivalent to:
(define (number->list n)
(define (loop n acc)
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc))))
(loop n '()))
Hopefully, that is easier for you to read and understand.
You might, then, ask why people tend to use a named let
rather than defining an internal function and invoking it. It's the same rationale people have for using (unnamed) let
: it turns a two-step process (define a function and invoke it) into one single, convenient form.
It's called a loop because the function calls itself in tail position. This is known as tail recursion. With tail recursion, the recursive call returns directly to your caller, so there's no need to keep the current call frame around. You can do tail recursion as many times as you like without causing a stack overflow. In that way, it works exactly like a loop.
If you'd like more information about named let
and how it works, I wrote a blog post about it. (You don't need to read it to understand this answer, though. It's just there if you're curious.)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…