scheme# How does the named let in the form of a loop work?

In an answer which explains how to convert a number to a list the `number->list`

procedure is defined as follows:

```
(define (number->list n)
(let loop ((n n)
(acc '()))
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc)))))
```

Here a "named `let`

" is used. I don't understand how this named `let`

works.

I see that a loop is defined where the variable `n`

is equal to `n`

, and the variable `acc`

equal to the empty list. Then if `n`

is smaller than 10 the `n`

is consed to the acc. Otherwise, "the loop" is applied with `n`

equal to `n/10`

and `acc`

equal to the cons of the remainder of `n`

/10 and the previous accumulated stuff, and then calls itself.

I don't understand why `loop`

is called loop (what is looping?), how it can automatically execute and call itself, and how it will actually add each number multiplied by its appropriate multiplier to form a number in base 10.

I hope someone can shine his or her light on the procedure and the above questions so I can better understand it. Thanks.

Solution

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.)

- Using AND with the apply function in Scheme
- Encode "ä", "ö", "ü" and "ß" in scheme (get german text from file)
- Combination of list-ref and index-of in racket
- How to undefine a variable in Scheme?
- Running Scheme from the command line
- Function that splits word
- How does the yin-yang puzzle work?
- Dr Racket Recursing Without Returning Inital Parent Node Within Function
- Chez Scheme FFI Procedure Doesn't Work After Change to Apple Silicon
- How do we convert this Scheme (Lisp) function into C#
- What is #~ in scheme?
- Racket : Run scheme file in terminal and show result
- Recursive numeric equality in Scheme
- Under any Scheme standard, is (let (x y z) x) valid code?
- Iterate through the letters of the alphabet in Racket
- What do Lisp macros have over functions that optionally evaluate their arguments?
- Delayed "let" in SICP
- Chicken Scheme pass on parameters to gcc
- Say we have an abstract data type for cities. A city has a name, a latitude coordinate, and a longitude coordinate
- Why doesn't this Scheme s-expression work when the sub expressions work?
- How do I read a web page in Racket?
- Why normal-order and applicative-order evaluation are not giving the same value?
- Implement a procedure remove that takes in a list and returns a new list with all instances of item removed from lst
- Lisp / Scheme : Evaluating nested empty list/cons : (())
- Converting a function with two recursive calls in scheme to make it tail-recursive
- GIMP: test.scm gets "unbound variable" error when run
- Upside down text
- how to redefine the function "range" in Racket/Scheme?
- Clearing the screen by printing a character?
- accumulative recursive function to produce a list of subtotals from last to first