大家好,我死了,我是liang tang。这篇文章在公共帐户中开始
我们继续参加肝脏伯克利CS61A的计划项目。今天,我们将讨论最后一部分,即其他问题部分。
尽管关于其他问题只有两个问题,但清楚地提出这两个问题并不容易,因此特别保留了解释全文。
课程
项目原始文档
github
让我们首先看一下问题:
在文件中完成功能后,它返回函数的替代方案。使我们的解释器支持递归。
类代表需要在其中评估的表达式。当非原子表达式返回类的实例。否则,它将始终调用该函数,直到函数返回值为一定值,而不是。
成功的实现需要以前的一些代码,包括已提供的源代码。所有递归调用都需要将其作为第三个参数传递到附加的呼叫。您的目标是确定可以使用尾部递归来优化哪种表达计算。
完成开发后,您需要打开以下评论:
完成后,测试:
回答我猜想,如果您没有看过相关的课程视频,您会感觉到云中的雾,我不知道尾巴是什么。
Tailing是递归场景中的优化场景,例如以下示例:
它也是计算步骤乘数。上面的方法是递归,并使用以下方法来迭代。它们的时间复杂性是相同的,所有o(n)。
问题在于,空间复杂性也是线性的,使用递归实现的空间复杂性,并且以下迭代方法所需的空间是恒定的级别。为什么有很大的差异?这是因为当我们是递归时,我们将每次回收时,创建一个新的环境来存储环境变量。每个递归是一层,您需要创建更多变量。
在此示例中,每次我们恢复进来时,我们都会创建两个值,总计最大递归n层。那么需要创建的变量数为O(n)。
但是,如果我们考虑一下,我们会发现这不是必要的。由于我们直接返回的是下一层递归的结果。当我们称之为递归时,这些参数已通过,当我们递归返回时,我们不要依靠任何环境变量。因此,当我们递归时,就无需保留电流。
换句话说,对于函数,当我们称其为本身时,两个参数已经完成了任务。在随后的递归执行过程中,它们不再需要它们,因此不必继续存储。被发布。
因此,在此优化之后,您可以降低尾部递归空间的复杂性,并且递归优化是指此。
显然,递归优化是有条件的。最大的条件是,递归中没有变量的依赖性。还可以理解,递归是函数背面的最后一步。例如,如果您仍然有一个步骤乘法器,请对其进行修改并将其更改为:
尽管这是类似的逻辑,但这不是递归。原因很简单,因为递归不再是以前要执行的最后一步,并且还有一个步骤。由于我们需要它,因此我们需要存储它的价值,也就是说,对于存储依赖,我们无法优化。
实际上,功能本身的逻辑并不复杂。已建立了代码框架老师。我们只需要根据意图实施它。
返回的含义是返回中间结果,而不是递归递归调用的环境。尽管我们创建了实例,但已经引入了所有现有对象,因此它不会带来太多的空间消耗,这可能类似于线性费用。
更复杂的地方是递归判断。我们需要找到一个可以重新出版的地方,并调用函数调用以添加附加参数。
有很多地方,我在下面列出:
只要了解递归原则,代码就完成了。
允许语言本身是由用户扩展的,可以简单地通过特殊类型实现。但是,必须以定义过程的形式实现它,并且它将创建一个过程,就像。但是,此过程具有特殊的评估规则:它首先应用参数,而不是评估参数,然后进行评估。
最终评估过程是在调用中,好像返回值粘贴到代码替换的代码一样。您可以参考以下示例:
上面的代码定义了一个名称,它的运行方式与此类似,但是它不需要关键字。它将此计算逻辑应用于此列表。
为了实现,为了改善功能,它创建一个实例并将其绑定在被传输的名称上。在本文中,更新功能,以便他可以支持语法。
暗示:
使用类中的功能使用表达式的表达式应用
测试您的代码:
回答我们观察到表达的组成。它的两个部分是定义部分,另一部分是逻辑部分,简单的缩写可能是格式:
我们并不难找到定义功能的所有部分。
以下是表达式的执行。我们会发现它将继承它,也就是说,它也是一个特殊的句子。呼叫的唯一方法是不同的呼叫方式。
根据提示,我们需要在类表达式的工作原理中实现该方法。逻辑实际上非常简单,并且可以非常简单地实现呼叫函数。
但是,在含义的提示下,我们需要自己阅读代码并找到它,因此仍然非常困难。
尽管只有两个其他问题,但并不难看到难度仍然没有明确定义的问题,这两个问题更加灵活,检查的范围更大。如果您可以做好这两个问题,那么可以肯定可以说是真正理解计划解释器的操作原理。不仅是方案,但实际上,其他编程语言的汇编和操作过程也具有飞行员窥视的影响豹子,可以说是值得的。
好吧,在这里,即使整个方案解释器的项目都完成,您如何认为它非常有意义?
原始:https://juejin.cn/post/7096765508283793421