当前位置:网站首页>有趣的 Kotlin 0x0E:DeepRecursiveFunction
有趣的 Kotlin 0x0E:DeepRecursiveFunction
2022-08-04 04:37:00 【AndroidKt】
前言
DeepRecursiveFunction 是 Kotlin 在 1.4.0 版本上尝试解决深度递归导致 StackOverflowError 问题的试行方案。在最新发布的 1.7.0 版本上正式 Stable。面对由于递归导致的栈溢出问题,一般我们采用两种解决办法:
- 增加栈大小
- 改写代码,采用非递归方式实现
Kotlin 通过定义 DeepRecursiveFunction 深度递归类型来实现非递归方式的改写。
官方建议:递归深度操作 1000 考虑使用 DeepRecursiveFunction。(Consider using deep recursive functions in your code where your recursion depth exceeds 1000 calls.)
语法
定义
public class DeepRecursiveFunction<T, R>(
internal val block: suspend DeepRecursiveScope<T, R>.(T) -> R
)
T为传入参数类型;R为输出结果类型;block函数体。
调用
public abstract suspend fun callRecursive(value: T): R
用于“递归”调用DeepRecursiveFunction
public operator fun DeepRecursiveFunction<*, *>.invoke(value: Any?): Nothing
操作符重载,以便 DeepRecursiveFunction 可以通过()操作符调用,当然也可以选择直接调用invoke函数。
看官方给出的示例对比,可能更直观一点。
示例
实现二叉树的深度计算:原始递归DeepRecursiveFunction。
原始递归
fun depth(t: Tree?): Int =
if (t == null) 0 else maxOf(
depth(t.left), // recursive call one
depth(t.right) // recursive call two
) + 1
DeepRecursiveFunction
val calculateDepth = DeepRecursiveFunction<Tree?, Int> {
t ->
if (t == null) 0 else maxOf(
callRecursive(t.left),
callRecursive(t.right)
) + 1
}
对比上面两种代码可以看出,开发者可以很容易从原始递归方式改写成 DeepRecursiveFunction 方式。这就是 Kotlin 希望达到的低开发成本效果。当开发者因采用原始递归方式时递归层级过深出现 StackOverflowError问题时, 简易调整为 DeepRecursiveFunction ,可以在避免大量改写代码的前提下帮助开发者快速解决栈溢出问题。
Run
fun main() {
// Generate a tree with a depth of 100_000
val deepTree = generateSequence(Tree(null, null)) {
prev ->
Tree(prev, null)
}.take(4).last()
println(calculateDepth(deepTree)) // 100000
println(depth(deepTree)) // 100000
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPAOp9KH-1659446563474)(http://qiniu.fultter.club/image-20220731130252997.png)]
源码
关于 DeepRecursiveFunction 的源码全部集中于 DeepRecursive.kt文件中,主要包含三个类:
- DeepRecursiveFunction
- DeepRecursiveScope
- DeepRecursiveScopeImpl
具体的实现集中在 DeepRecursiveScopeImpl 类中,通过协程机制实现递归逻辑。
suspend 模拟向下压栈 ️,resume 模拟向上出栈 ️,实现类似递归调用的效果🪆。
结语
每一颗语法糖背后,总有几个 Kotlin 的工程师在为我们负重前行。🥸
边栏推荐
- XSS相关知识点
- drools from download to postman request success
- 【MD5】采用MD5+盐的加密方式完成注册用户和登录账号
- 【技巧】借助Sentinel实现请求的优先处理
- ADC噪声全面分析 -03- 利用噪声分析进行实际设计
- 烧录场景下开发如何进行源代码保密工作
- Postgresql源码(66)insert on conflict语法介绍与内核执行流程解析
- There is an 8 hour difference between the docker installation of mysql and the host.
- 外卖店优先级
- 【机器学习】21天挑战赛学习笔记(一)
猜你喜欢

小程序 + 电商,玩转新零售

【 observe 】 super fusion: the first mention of "calculate net nine order" evaluation model, build open prosperity of power network

The Shell function

结构体函数练习

烧录场景下开发如何进行源代码保密工作

share总结

看DevExpress丰富图表样式,如何为基金公司业务创新赋能

How to simplify the automation of modern e-procurement?

Eight guiding principles to help businesses achieve digital transformation success

深度学习21天——准备(环境配置)
随机推荐
drools from download to postman request success
八年软件测试工程师带你了解-测试岗进阶之路
Oracle与Postgresql在PLSQL内事务回滚的重大差异
【流程图】
7. The principle description of LVS load balancing cluster
深度学习21天——卷积神经网络(CNN):实现mnist手写数字识别(第1天)
How to systematically plan and learn software testing?
How to open a CITIC Securities online account?is it safe?
7-2 LVS+DR Overview and Deployment
2022软件测试面试题 最新字节跳动50道真题面试题 刷完已拿下15k 附讲解+答疑
XSS相关知识点
Jenkins 导出、导入 Job Pipeline
Functions, recursion and simple dom operations
The video of machine learning to learn [update]
FFmpeg —— 录制麦克风声音(附源码)
ADC噪声全面分析 -03- 利用噪声分析进行实际设计
Enterprise live broadcast is on the rise: Witnessing focused products, micro-like embracing ecology
大型连锁百货运维审计用什么软件好?有哪些功能?
21 days learning challenge 】 【 sequential search
PHP高级开发案例(1):使用MYSQL语句跨表查询无法导出全部记录的解决方案