当前位置:网站首页>有趣的 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 的工程师在为我们负重前行。🥸
边栏推荐
- 杭电多校-Slipper-(树图转化+虚点建图)
- 元宇宙“吹鼓手”Unity:疯狂扩局,悬念犹存
- 小程序 + 电商,玩转新零售
- Mockito unit testing
- How to dynamically add script dependent scripts
- 初识Numpy
- Embedded database development programming MySQL (full)
- 烧录场景下开发如何进行源代码保密工作
- 信息学奥赛一本通 1312:【例3.4】昆虫繁殖
- There is an 8 hour difference between the docker installation of mysql and the host.
猜你喜欢

【流程图】

How to keep the source code confidential in the development under the burning scenario

Explain详解与实践

Shell 函数

10 Convolutional Neural Networks for Deep Learning 3

Converts XML tags to TXT format (voc conversion for yolo convenient training)

7-2 LVS+DR概述与部署

张量篇-应用案例

Hey, I had another fight with HR in the small group!

Postgresql源码(66)insert on conflict语法介绍与内核执行流程解析
随机推荐
For Qixi Festival, I made a confession envelope with code
How to keep the source code confidential in the development under the burning scenario
小程序 + 电商,玩转新零售
Introduction to mq application scenarios
A Preliminary Study of RSS Subscription to WeChat Official Account-feed43
mysql索引笔记
深度学习环境配置
FFmpeg —— 通过修改yuv,将视频转为黑白并输出(附源码)
目标检测-中篇
机器学习模型的“可解释性”
Mini program + e-commerce, fun new retail
Stop behind.
SQL query String field less than 10 how to check
Functions, recursion and simple dom operations
软件测试如何系统规划学习呢?
pnpm 是凭什么对 npm 和 yarn 降维打击的
PHP高级开发案例(1):使用MYSQL语句跨表查询无法导出全部记录的解决方案
看DevExpress丰富图表样式,如何为基金公司业务创新赋能
This Thursday evening at 19:00, the fourth live broadcast of knowledge empowerment丨The realization of equipment control of OpenHarmony smart home project
How class only static allocation and dynamic allocation