Racket中使用Y组合子
关于Y组合子,网上已经介绍很多了,其作用主要是解决匿名lambda的递归调用自己。
首先我们来看直观的递归lambda定义,
假设要定义阶乘的lambda表达,C#中需要这么定义
Func<int, int> fact = null;
fact = x => x <= ? : x * fact(x - );
这种方法非常简单直接,当然问题也存在,因为这里fact其实是一个委托对象,当这个对象改变后,可能就得不到阶乘的效果了。
在scala中则是这样,
def F: Int => Int = (n:Int) => if(n == 0) 1 else n* F(n - 1)
嗯,在本文的主打语言Racket中,则变成这样
(define F
(lambda (n) (if (equal? n ) (* n (F (- n ))))))
由于这个函数F定义中使用了F自身,那么如何修改可以去掉这个F?
现在变化一下,增加一个函数参数f,以使的我们调用F时,可以把自身传递进去,那样就解决了前面F的定义中使用了F自身的问题,修好后如下
(define FF
(lambda (f) (lambda (n) (if (equal? n ) (* n ((f f) (- n )))))))
这样调用((FF FF) 5)就能得到120这个结果了。
当然这里我们甚至可以不用define这个关键字来给这个lambda定义一个名字,直接上lambda本体,如下
(((lambda (f) (lambda (n) (if (equal? n )
(* n ((f f) (- n ))))))
(lambda (f) (lambda (n) (if (equal? n )
(* n ((f f) (- n ))))))) )
同意可以得到正确结果120。
上面这个方法算是比较直接,一个更加优雅的解决方法当然就是本文的主jiao:Y组合子
Y组合子
Y = λf. (λx. f (x x)) (λx. f (x x))
一种使用Racket的表示为
(define Y
(lambda (f) ((lambda (x) (f (lambda (y) ((x x) y))))
(lambda (x) (f (lambda (y) ((x x) y)))))))
这样,阶乘的lambda表示为
(define Fact
(Y (lambda (f) (lambda (n) (if (equal? n ) (* n (f (- n ))))))))
斐波那契的lambda表示为
(define Fib
(Y (lambda (f) (lambda (n) (if (< n ) (+ (f (- n )) (f (- n ))))))))
这里,关键点在于,Y的参数为一个函数,比如阶乘中是
(lambda (f) (lambda (n) (if (equal? n )
(* n (f (- n ))))))
这个表达式中可以用f表示自身。
Racket中使用Y组合子的更多相关文章
- Lambda演算 - 简述Y组合子的作用
Y组合子:\f.(\x.f(xx))(\x.f(xx)),接受一个函数,返回一个高阶函数 Y组合子用于生成匿名递归函数. 什么叫匿名递归函数,考虑以下C语言递归函数 int sum(int n) { ...
- 大到可以小说的Y组合子(一)
问:上回乱扯淡了一通,这回该讲正题了吧. 答:OK. 先来列举一些我参考过,并从中受到启发的文章. (1.)老赵的一篇文章:使用Lambda表达式编写递归函数 (2.)装配脑袋的两篇文章:VS2008 ...
- 大到可以小说的Y组合子(三)
答:关于Fix的问题你fix了吗? 问:慢着,让我想想,上次留下个什么问题来着?是说我们有了一个求不动点的函数Fix,但Fix却是显式递归的,是吧? 答:有劳你还记的这个问题. 问:Fix的参与背离了 ...
- 大到可以小说的Y组合子(零)
问:啊!我想要一个匿名的递归… 答:Y(音同Why)… … … 问:作为一位命令式语言的使用者,为什么会突然折腾起Y组合子呢? 答:的确,这事儿要从很久以前的几次搁浅开始说起…上学的时候,从来没有接触 ...
- 简单易懂的程序语言入门小册子(4):基于文本替换的解释器,递归,如何构造递归函数,Y组合子
递归.哦,递归. 递归在计算机科学中的重要性不言而喻. 递归就像女人,即令人烦恼,又无法抛弃. 先上个例子,这个例子里的函数double输入一个非负整数$n$,输出$2n$. \[ {double} ...
- Y组合子
Y组合子 Y组合子的用处 作者:王霄池链接:https://www.zhihu.com/question/21099081/answer/18830200来源:知乎著作权归作者所有.商业转载请联系作者 ...
- 大到可以小说的Y组合子(二)
问:上一回,你在最后曾提到"抽象性不足",这话怎么说? 答:试想,如果现在需要实现一个其它的递归(比如:Fibonacci),就必须把之前的模式从头套一遍,然后通过fib_make ...
- 用不动点组合子解递归(python实现)
不动点组合子 Y = λf. (λx. f (x x)) (λx. f (x x)) θ = (λx. λy. (y(x x y))) (λx.λy.(y(x x y))) Y f = f (Y f) ...
- [学习] 从 函数式编程 到 lambda演算 到 函数的本质 到 组合子逻辑
函数式编程 阮一峰 <函数式编程初探>,阮一峰是<黑客与画家>的译者. wiki <函数编程语言> 一本好书,<计算机程序的构造与解释>有讲到schem ...
随机推荐
- 关于ADO.NET参数化查询的提问
最近我们的正式环境一直在报错一个异常,首先我贴出来异常信息 BLL层 捕获到了请求的url Net.BLL.MobileFun MobileFun.GetBusinessBidPolicy 异常 传入 ...
- ASP.NET WebApi 入门
今天参照微软官方(http://www.asp.net)学习了WebApi,在这里摘录如下: 前言 HTTP 不只是为了生成 web 页面.它也是一个强大的平台,可以建设公开服务和数据的 Api.HT ...
- ubuntu-使用终端配置网络
文件说明: IP.网关.掩码的配置文件:/etc/network/interfaces DNS配置文件:/etc/resolv.conf 配置步骤: 1)配置有关IP文件 配置IP.网关.掩码这些信息 ...
- 记录在IIS中安装部署Orchard遇到的问题
本机环境:Windows 8.1 + IIS8.5 + VS2013+SQLServer2012 首先是从官网直接下载Orchard.Web 1.7.2版的安装包,在本机IIS上部署,按官方文档一步步 ...
- [转]Mac's and serial TTY's
Mac's are excellent tools for accessing serial device TTY ports (to console into PBX's, switches, an ...
- [RM 状态机详解4] RMNode状态机详解
摘要 RMNode状态机是ResourceManager的四个状态机(RMApp,RMAppAttempt,RMContainer,RMNode)中最简单的一个,状态机如图1所示.RMNode是Res ...
- npm ERR! Error: socket hang up
when i use npm to install express, it goes this message: npm info it worked if it ends with ok npm i ...
- Jquery文本框值改变事件(支持火狐、ie)
Jquery值改变事件支持火狐和ie浏览器,并且测试通过,绑定后台代码可以做成autocomplete控件. 具体代码列举如下: $(document).ready(function () { $(& ...
- jQuery中delegate与on的用法与区别
在jQuery1.7中 .delegate()已被.on()取代.对于早期版本,它仍然使用事件委托的最有效手段. 在事件绑定和委派,delegate()和on在一般情况下,这两种方法是等效的. .de ...
- 快速开发平台WebBuilder中ExtJS表格的增删改查
使用WebBuilder可实现表格的自动增删改查功能,而无需编写前台脚本和后台SQL. WebBuilder开源项目地址:http://www.putdb.com 自动生成的页面: <!DOCT ...