这个问题是关于一种名为“Liquid”的高级模板语言。为什么我标记了它的组装?因为我认为汇编程序员有更多使用手动处理多次递归的经验。
在液体中,您可以通过包含具有特定参数的文件来创建“功能”:
{% include file var1="a" var2="b" %}
到目前为止一切顺利 - 如果我们有办法返回,我们可以用这个创建一个有效的多重递归循环。
不幸的是,液体是我见过的最残疾的逻辑形式之一。它几乎没有完成。没有返回值,没有范围,数组只是您可以拆分的字符串。
使用我正在编写的多重递归函数,全局变量会受到子句的破坏。我甚至没有堆栈可以在这里工作!
如果我在树节点上设置布尔值true并递归到较低节点,如果任何较低节点(或同一级别的后续节点)设置它,它将破坏较高节点的活动值。
这有点限制了我的选择:
我想要神秘的逻辑!
利用活动总是向上传播的事实,应该有一些操作顺序可以正确地完成它,但是我一直在抨击我的头3天而且我无法直接思考。
Here is the code in question虽然阅读可能会让这更令人困惑。
答案 0 :(得分:2)
编译器(和asm程序员)通过在堆栈上按状态,进行调用,然后从堆栈弹出状态来实现多次递归。因此局部变量和args在堆栈中。
只要有足够的堆栈空间用于最大调用深度,这就可以递归地工作。
我认为要使递归工作(当然除了尾递归),你需要实现一些可以用作堆栈的数据结构,将状态推到它上并将其弹回。
完全通用的递归要求能够以任何需要的深度保存和恢复状态。
如果你没有任何可变大小的存储,你可以实现一个小的固定大小的堆栈,其中包含全局变量,如stack1,stack2,stack3等,以及一个计数器作为堆栈指针。您只需要与递归的最大深度一样多的变量。
但是,您可能能够使用实际上不递归的函数来实现您的特定算法。你说过穿越一棵树吗?也许请参阅Write a non-recursive traversal of a Binary Search Tree using constant space and O(n) run time了解相关内容。其中一些涉及修改树。当然,如果你的树节点有父指针,那么遍历很容易,因为你可以在一边走后找到自己的方式。
答案 1 :(得分:0)
在我的递归包含中我这样做
{% assign n = include.n %}
{% if n == nil %}
{% assign n = 0 %}
{% endif %}
++++ Do something on n
{% assign n = n | plus: 1 %}
{% if n < something %}
{% include self.html n=n %}
{% endif %}
++++ Reverse value of n to parent value
{% assign n = n | minus: 1 %}