进一步优化还可以用 JDK 的 Thread local storage,因为每个线程同时只能运行一个函数。
换句话说一个线程对 infixChain() 函数调用有一个栈就够了,用完 clear() 就可以,这是个存储分配方面的优化。
当然,如果你的那个 fun 是 suspend fun 当我没说
为了兼容性这个优化我没有做。
换句话说一个线程对 infixChain() 函数调用有一个栈就够了,用完 clear() 就可以,这是个存储分配方面的优化。
当然,如果你的那个 fun 是 suspend fun 当我没说
为了兼容性这个优化我没有做。
duangsuse::Echo
运行的时候就是这样
然后咱再来测试一下
一确保算法在多个 Tail 同时出现的情况下(看起来)可以正常工作。
0 + 1 * 2 ** 3 这种情况,假定 (**) 也是左结合的:一确保算法在多个 Tail 同时出现的情况下(看起来)可以正常工作。
噢是我定义新前缀的时候搞错了,本来是 ascending order 的 🐱
我们注意到,本来是 0+ 2*
(0+) 的提前和 2 弄混了…… 都是在扫描 rest 的时候搞的
看来还是思路错了…… Tail 是不可能被铺平的,除非你真不用伪递归(就是基于
(0+) 的提前和 2 弄混了…… 都是在扫描 rest 的时候搞的
看来还是思路错了…… Tail 是不可能被铺平的,除非你真不用伪递归(就是基于
Recursion<T> 的递归)
duangsuse::Echo
我们注意到,本来是 0+ 2* (0+) 的提前和 2 弄混了…… 都是在扫描 rest 的时候搞的 看来还是思路错了…… Tail 是不可能被铺平的,除非你真不用伪递归(就是基于 Recursion<T> 的递归)
突然觉悟了,为什么 Tail 里面必须是 Atom 啊?也可以是递归的 Tail 啊!
不过这样就等于是白建一个栈了……
不过这样就等于是白建一个栈了……
我想到一种很自然的解决方法:
把栈表达为 [Base(0), Tail(+), Base(2), Tail(*), Base(3!4!1)] 的形式
然后我们回溯的时候修改一下策略,让它结合 lhs=pop() 就可以了
把栈表达为 [Base(0), Tail(+), Base(2), Tail(*), Base(3!4!1)] 的形式
然后我们回溯的时候修改一下策略,让它结合 lhs=pop() 就可以了
回溯完成,得
每次由归纳程序 reduce 从栈上 pop 出一个项目
如果是 join,则 join 又会从栈上 pop 一个项目,作为 reduce 的 base
不过这样实际上就作了一个断言:栈后面的全是结合性弱的,而且这部分全都是往右结合
我相信这断言是正确的,因为如果有打破它的情况,早就在 stack.mapTop {} 的时候被结合了
2 正确。每次由归纳程序 reduce 从栈上 pop 出一个项目
如果是 join,则 join 又会从栈上 pop 一个项目,作为 reduce 的 base
不过这样实际上就作了一个断言:栈后面的全是结合性弱的,而且这部分全都是往右结合
我相信这断言是正确的,因为如果有打破它的情况,早就在 stack.mapTop {} 的时候被结合了
Calc.kt
4.7 KB
新的,带基于栈的 infix 链扫描算法的 Calc.kt 例子
duangsuse::Echo
Calc.kt
这是上一个,只比它小 1K
现在是愉快的跑分时间~
我将随机生成 5个甚至2 个字符长度的 number,性能优化dssq。
2 个甚至 1 个的空白 ' '
[+-*/!] 里随机选的中缀
重复 5k 个这样的
然后比较两个算法(递归 vs. 显式栈)处理的性能(时间开销)
我将随机生成 5个甚至2 个字符长度的 number,性能优化dssq。
2 个甚至 1 个的空白 ' '
[+-*/!] 里随机选的中缀
重复 5k 个这样的
0 {op whitespace num} 然后比较两个算法(递归 vs. 显式栈)处理的性能(时间开销)