cps/trampoline
eopl 第五、六两章谈的就是这个问题。
我写了一个 python 版本的程序,先挖个坑,然后等彻底看完再补上。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# the cps version
def s(n, f):
if n < 1:
return f(n)
return s(n-1,
lambda x: f(x + n))
# the trampoline version
def t_s(n, f):
if n < 1:
return lambda :f(n)
return lambda : t_s(n-1, lambda x: f(x + n))
def trampoline(f):
while hasattr(f, '__call__'):
f = f()
return f
if __name__ == '__main__':
print s(10, lambda x: x)
print trampoline(t_s(10, lambda x: x))
下面是一个稍微复杂的例子,计算 fibonacci
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def trampoline(f):
while hasattr(f, '__call__'):
f = f()
return f
# the fibonacci
def fib_cps(n, f):
"""
Arguments:
- `n`: the number of fibonacci
- `f`: the contiunation
"""
if n < 2:
return f(1)
return fib_cps((n-1),
lambda x: fib_cps((n-2),
lambda y: f(x + y)))
def fib_tramp(n, f):
if n < 2:
return lambda : f(1)
return lambda : fib_tramp(n-1,
lambda x: lambda : fib_tramp(n-2,
lambda y: lambda: f(x + y)))
if __name__ == '__main__':
print fib_cps(10, lambda x: x)
print trampoline(fib_tramp(10, lambda x: x))
cps/trampoline的更多相关文章
- 基于CPS变换的尾递归转换算法
前言 众所周知,递归函数容易爆栈,究其原因,便是函数调用前需要先将参数.运行状态压栈,而递归则会导致函数的多次无返回调用,参数.状态积压在栈上,最终耗尽栈空间. 一个解决的办法是从算法上解决,把递归算 ...
- 探索c#之递归APS和CPS
接上篇探索c#之尾递归编译器优化 累加器传递模式(APS) CPS函数 CPS变换 CPS尾递归 总结 累加器传递模式(Accumulator passing style) 尾递归优化在于使堆栈可以不 ...
- cps变换
网上看了很多内容,很少有给出一个准确的概念,它的英文全称是continuous passing style, 直译为连续传递样式,那么cps transform就是将一些原本不是continuous ...
- 如何设计一门语言(八)——异步编程和CPS变换
关于这个话题,其实在(六)里面已经讨论了一半了.学过Haskell的都知道,这个世界上很多东西都可以用monad和comonad来把一些复杂的代码给抽象成简单的.一看就懂的形式.他们的区别,就像用js ...
- Scalaz(35)- Free :运算-Trampoline,say NO to StackOverflowError
在前面几次讨论中我们介绍了Free是个产生Monad的最基本结构.它的原理是把一段程序(AST)一连串的运算指令(ADT)转化成数据结构存放在内存里,这个过程是个独立的功能描述过程.然后另一个独立运算 ...
- 什么是CPA, CPS, CPT?
在互联网上或移动端进行产品推广时,经常听到很多术语,什么CPA,CPS,CPT等等.不知是怎么来的,今天网上搜一下术语,在这里做一下笔记. CPA(Cost Per Action) 每行动成本. CP ...
- CPS冥想 - 2 手撸控制流
原博客链接:http://blogs.msdn.com/b/ericlippert/archive/2010/10/22/continuation-passing-style-revisited-pa ...
- CPS冥想 - 1 重新审视CPS
这篇文章是在阅读Eric Lippert大神的MSDN Blog文章时同步写成的,其中主要是各种翻译,同时还混杂自己阅读文章的笔记和感想. 原博文地址 http://blogs.msdn.com/b/ ...
- haskell中的cps
cps全称叫continuation passing style,简要来讲就是告诉函数下一步做什么的递归方式,由于普通递归有栈溢出的问题,而cps都是尾递归(tail recursion),尾递归则是 ...
随机推荐
- HDFS基本工作机制
- centos7通过阿里云配置docker加速镜像
针对Docker客户端版本大于1.10.0的用户 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器: sudo mkdir -p /etc/docker s ...
- python widows安裝scipy
https://blog.csdn.net/github_39611196/article/details/76718707 Python3.x直接运行pip install scipy即可.Pyth ...
- myeclipse中更改web项目在tomcat中部署的路径
右键点击项目名称,选择属性properties,选择myeclipse->web.更改web context-root就可以.
- HTTP来源地址
HTTP来源地址(referer,或HTTP referer),是HTTP表头的一个字段,用来表示从哪儿链接到目前的网页,采用的格式是URL. 换句话说,借着HTTP来源地址,目前的网页可以检查访客从 ...
- Linux下多线程的重要知识点
线程属性: typedef struct { int detachstate; 线程的分离状态 int ...
- 读取xml文件,写入excel
在上一篇 Python写xml文件已经将所有订单写入xml文件,这一篇我们把xml文件中的内容读出来,写入excel文件. 输入xml格式: <?xml version="1.0&qu ...
- nodejs 异步编程 教程(推荐)
有异步I/O就需要异步编程.本课程将着重讲解在学习node.js中关于异步编程的一些问题,以及如何应对这些问题,帮助node.js初学者快速入门. 地址 http://www.hubwiz.com/c ...
- std::bind
参考资料 • cplusplus.com:http://www.cplusplus.com/reference/functional/bind/ • cppreference.com:http://e ...
- 在vue中使用express-mock搭建mock服务
首先安装 nodemon ,如果是全局安装,那么所有的项目都可以使用mock服务 npm install nodemon 再安装express-mockjs npm i -D express-mock ...