免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1641 | 回复: 7
打印 上一主题 下一主题

尾递归优化的含义 [复制链接]

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-08-25 13:18 |只看该作者 |倒序浏览
一直不明白尾递归优化是如何做到的, 今天突然灵光一闪, 好像明白了:


  1. call(a,b, call(c, d, call(e,f)))
复制代码



  1. my $return = call(e,f);
  2. for (call(c, d), call(a, b)) {
  3.    my $return = call(c, d, $return)
  4. }

复制代码


这里的调用不是参数调用, 是表达式展开. 每次将计算的结果, 添加到表达式的末尾.
   

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
2 [报告]
发表于 2016-08-27 18:20 |只看该作者
大神能否说下, 这个东西用在啥地方?

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
3 [报告]
发表于 2016-08-28 00:39 |只看该作者
尾递归优化的概念是从编译器出来的,
如果是设计语言的就知道,函数的设计会有一个局部的堆栈空间。
如果递归太深的话,这个堆栈就会超出设计容量。采用这种技术,可以用堆空间置换堆栈空间。

这种技术如果用在优化代码上,可以对不支持尾递归优化的语言进行手动优化。提高效率。

Java 就不支持尾递归优化。另外许多语言的函数栈都有容量限制。

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
4 [报告]
发表于 2016-08-29 11:04 |只看该作者
你这不对啊。

尾调用(tail call)指的是 一个函数(A)return 语句返回的是一个函数调用(B),那局部变量显然不会再用到了可以直接从栈上删除(引用,closure 什么的由GC负责),B的返回地址可以直接替换为 A 的,这样可以节省A占用的栈空间。

如果 A 里调用的还是 A 或者几个不同函数互相调用,这就叫尾递归,这样优化使栈不会不断增长。

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
5 [报告]
发表于 2016-08-29 11:07 |只看该作者
至于具体怎么做设计个简单的只支持一条占用栈的空指令和函数调用的虚拟机就明白了

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
6 [报告]
发表于 2016-08-29 14:12 |只看该作者
zhlong8 发表于 2016-08-29 11:04
你这不对啊。

尾调用(tail call)指的是 一个函数(A)return 语句返回的是一个函数调用(B),那局部 ...

看我的例子就知道,只有表达式最后一个调用是函数本身,才能被优化。

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
7 [报告]
发表于 2016-08-29 14:12 |只看该作者
本帖最后由 104359176 于 2016-08-29 14:20 编辑

最简单的一个例子就是 map 的嵌套
  1. map { expr } map { expr } map { expr } @array;
  2. my @return = map { expr  } @array;
  3. for (1,2) {
  4.   @return = map { expr } @return;
  5. }
  6.    
复制代码
@array[/code]:
可以优化成:



论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
8 [报告]
发表于 2016-08-29 21:41 |只看该作者
我不明白把返回值替换成中间变量和主题有什么关系
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP