循环形式的命名 let 是如何工作的? [英] How does the named let in the form of a loop work?

查看:31
本文介绍了循环形式的命名 let 是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个答案中,解释了如何将数字转换为列表number->list 过程定义如下:

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

这里是一个名为 let"用来.我不明白这个名为 let 的工作原理.

Here a "named let" is used. I don't understand how this named let works.

我看到定义了一个循环,其中变量 n 等于 n,变量 acc 等于空列表.然后,如果 n 小于 10,则 n 被分配给 acc.否则,应用循环"时 n 等于 n/10 并且 acc 等于 n 余数的 cons/10 和之前积累的东西,然后调用自己.

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.

我不明白为什么 loop 被称为循环(什么是循环?),它如何自动执行和调用自己,以及它如何实际将每个数字乘以适当的乘数相加到形成一个以 10 为底的数字.

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.

推荐答案

命名 let 背后的基本思想是它允许您创建一个内部函数,该函数可以调用自身并调用它自动地.所以你的代码相当于:

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.

然后,您可能会问,为什么人们倾向于使用命名的 let 而不是定义内部函数并调用它.这与人们使用(未命名)let 的基本原理相同:它将两步过程(定义一个函数并调用它)变成一个单一的、方便的形式.

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.

如果您想了解有关命名 let 及其工作原理的更多信息,我写了一个关于它的博文.(不过,您不需要阅读它来理解这个答案.如果您好奇,它就在那里.)

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

这篇关于循环形式的命名 let 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆