2019独角兽企业重金招聘Python工程师标准>>>

之前的只是开胃小菜,在确保你能弄懂前面的代码例子后再来看这个。这个能弄懂表示你已经彻底搞懂了闭包是怎么回事了。

前面的例子中,我们最终还是需要一个数来表示一个起始的数。那么还没有完全达到我们的目的。但是如果要完全用函数来代替数,我们又怎么证明一个函数确实是表示那个数呢?

为此,我们需要先考察一下数到底是怎么回事。

想想最原始的表示数的方法:用指头数数,当10个指头数完了,数就到头了,如果你是一个牧羊人,有超过十头的羊,还可以用来表示比10更大的数。但是当人类想明白5个指头和5头羊之间的联系是什么的时候,他们就不用再用5头羊或5个指头来表示5,而只要说出数字5的符号就可以了,这时人类完成了一次抽象概念提取的过程。

因此,最原始的数的概念:一个数就是表示一件事物重复的次数。

想象一个在完全只有函数,而没有数的世界里,怎么计数?方法就是,对这个函数传入一个函数执行(注意,没有数了),这个函数的内容被执行N遍,就表示执行这个函数的函数代表的是N这个数了。

因此,假设有一个函数能代表0

zero = f(x)

还有一个函数能代表加1

incr = f(x)

那么1就能表示为

one = incr(zero)

2表示为

two = incr(incr(zero))

更多的数表示为

three = incr(incr(incr(zero)))
four = incr(incr(incr(incr(zero))))
five = incr(incr(incr(incr(incr(zero)))))
…………
自然数N能表示为incr的N次方(zero)

所以,我们首先要定义一个函数用来表示zero,和incr,这样就能表示其他所有的数了

接下来,这是zero的表示

function zero(f){return function(x){return x;}
}

这个函数表示的意思是,传入一个函数f,zero会返回给你一个函数,用zero返回的函数,再传入一个x,这时zero返回的函数会把这个x原样返回。这个函数看起来没什么用,但是它符合前面我们对表示数的函数的定义,传入f,它一次都不会被执行。那么x在这里是干什么的呢?

x本身无任何意义,它只是用来占位的。表示一个数存在的边界,这有点像C语言字符串数组中的'\0',任何字符串数组中都不会显示它,但任何字符串数组都离不开它。

注意:接下来你会看到很多形如n(f)(x)的式子,为了大家在看的时候不犯晕,这里着重强调一下,希望大家牢记在心:如果n是一个表示函数的数的话,那么n(f)(x)的意思就是把f(x)调用n次。

你也许会认为用一个repeat(n,f,x)的函数可以做同样的事情,但我需要提醒你的是:首先,n不是一个数字,n是一个关于几是几的抽象。此外这种设计会得到一个比repeat更抽象,灵活,强大的函数,希望你能在后面领悟得到。

在这个例子中我们用两个打印鸭子的函数来表示f,x,f打印黄鸭子,表示的是增1,x打印绿色鸭子,表示的是0。

function yellowduck(x){print('<img src="http://thumbs.dreamstime.com/thumbimg_426/1249659187Yb2Igm.jpg">');
}
function greenduck(x){print('<img src="http://www.greenduck.co.uk/images/about/logo.gif">');
}

注意到,两个方法中的入参在我们这里的示例中其实没有任何作用,因为不管传入的x是什么,都只打印一只鸭子而已。

尴尬的是,传入的打印绿鸭子的方法从来不会被调用,就好比我们在每一个字符串数组中都添加了\0,但\0从来不会被显示一样。因此,还需要专门写一个方法来查看打印数的情况,人为的在打印完原数后再打印一只绿鸭子表示结尾,printduck只是为了方便我们查看一个数而已。

function printduck(n){n(yellowduck)(greenduck);//greenduck never be called at this line;greenduck(null);//execute it manually;
}

如果看到一个函数被执行,打印出一只绿鸭子,表示为0,打印出一只黄鸭子后面跟一只绿鸭子表示此数为1。

这是打印0的代码。

 <!DOCTYPE html>
<html>
<body>
<script language="javascript" type="text/javascript">
<!--
function print(){var vars = print.arguments;var arr = [];for (var i = 0; i < vars.length; i++){  arr.push(vars[i]);  }  document.write(arr.join(',')+'<br/>');
}function yellowduck(x){print('<img src="http://thumbs.dreamstime.com/thumbimg_426/1249659187Yb2Igm.jpg">');
}
function greenduck(x){print('<img src="http://www.greenduck.co.uk/images/about/logo.gif">');
}function zero(f){return function(x){return x;}
}function printduck(n){n(yellowduck)(greenduck);//greenduck never be called at this line;greenduck(null);//execute it manually;
}

接下来再看增1是如何定义的

function incr(n){return function(f){return function(x){return f(n(f)(x));  }}
}

看着 是不是有点晕?别急,让我们拆开来看里面的函数,把一行拆成两行就好理解了。

function incr(n){return function(f){return function(x){executed = n(f)(x);return f(executed);  }}
}

前面着重说了,形如n(f)(x)的式子,表示将f(x)执行n遍。因此该函数就是在执行n遍后,再一次调用f(x),不就是增加一遍了吗?

试想当我们执行incr(zero)(yellowduck)(greenduck)的时候。我们得到的是

yellowduck(zero(yellowduck)(greenduck));

前面已经分析过,zero(f)(x)不会执行任何东西。因此,式子的结果就是yellowduck被执行一次。

所以

one = incr(zero);

再来看 incr(one)(yellowduck)(greenduck)的情形,等于

yellowduck(one(yellowduck)(greenduck));

而one(yellowduck)(greenduck)又等于yellowduck(zero(yellowduck)(greenduck));带入上式,得到

yellowduck(yellowduck(zero(yellowduck)(greenduck)));

将这个过程一直持续下去,我们将得到

n = yellowduck(yellowduck........(yellowduck(zero(yellowduck)(greenduck)));

等于调用了n次yellowduck(x),和我们之前的定义是完全一致的。

我们可以执行来看看实际情况如何

var one = incr(zero);
var two = incr(one);
var three = incr(two);printduck(one);
printduck(two);
printduck(three);

神奇的事情发生了!在我们的例子中确实没有一个数的存在,但我们确实用函数组成的函数,把数的概念给表达了出来!

(待续)

转载于:https://my.oschina.net/ueharaai/blog/145010

如何用函数表示数(四)数的彻底消失相关推荐

  1. Leetcode(18)-四数之和

    给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满 ...

  2. 二数和,三数和,四数和的优化总结

    1.你以为很简单的两数之和 leetcode上你只用输出一组就好了, 但如果有重复数字呢? 比如 [1,2,2,3], target = 4 这个时候有两组解 [1,3], [2, 2] 如果给出的测 ...

  3. 4. Leetcode 18. 四数之和 (数组-双向双指针)

    给你一个由 n 个整数组成的数组 nums ,和一个目标值 target .请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] ( ...

  4. LeetCode 17电话号码的字母组合(搜索)18四数之和

    电话号码的字母组合 题目描述 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 示例: 输入:"23 ...

  5. 算法笔记-两数之和、三数之和、四数之和(LeetCode)

    两数之和 1.两数之和 题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数 ...

  6. java小编程----四数之和

    给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满 ...

  7. leetcode 454. 4Sum II | 454. 四数相加 II(Java)

    题目 https://leetcode.com/problems/4sum-ii/ 题解 四数相加问题. 对于左边两个数两两组合,需要维护一个 map,用来存左边两个数的 sum 以及该 sum 对应 ...

  8. 四数之和Python解法

    给你一个由 n 个整数组成的数组 nums ,和一个目标值 target .请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] ( ...

  9. 两数、三数、四数之和相关题目(Leetcode题解-Python语言)

    作为 Leetcode 的第一题,两数之和自然是知名度最高的,从两数之和出发也有不少的衍生题目,下面就让我们好好地解决它们. 1. 两数之和 class Solution:def twoSum(sel ...

  10. LeetCode 454. 四数相加 II 思考分析

    题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单化,所有 ...

最新文章

  1. crontab 最小间隔_今天我间隔了:如何找到不在数组中的最小数字
  2. 解决weblogic Managed Server启动非常慢的情况
  3. 2011.03.16中国食盐价格不上涨,日本不缺少食盐。
  4. php ajax 注册,非常实用的ajax用户注册模块
  5. vst3插件_Blue Cat Audio Blue Cat PatchWork mac(蓝猫桥接插件)
  6. 【机器视觉】 if算子
  7. 很大的.xls 文件导入sqlserver2005导入不全_python3 接口测试数据驱动之操作 excel 文件...
  8. keil的configuration wizard配置和使用
  9. 转载:扒一扒Profiler中这几个“占坑鬼”
  10. AutoCAD2012从入门到精通中文视频教程 第16课 渐变填充,椭圆弧命令(个人收藏)
  11. 360手机助手pc版 v2.4.0.1265 官方版
  12. html如何让字体变形,jquery实现字体变形特效-css字体变成圆形
  13. 2018 ISC | 最炫酷的展台和最火爆的分论坛
  14. JavaScript CSS jQuery 网页音乐播放器
  15. [异常退出,错误代码0xC0000005]:解决Windows应用程序崩溃的问题
  16. 【SVM分类】基于狮群算法优化实现SVM数据分类matlab源码
  17. BIM模型文件下载——施工场地部署模型
  18. 存储主控芯片亚洲新势力崛起
  19. 【SSL】2299护卫队
  20. 小米电视更换默认桌面和优化

热门文章

  1. 使用思科路由器防御DDOS
  2. jdk动态代理实例和cglib动态代理实例_CGLib 动态代理 原理解析
  3. Xamarin图表开发基础教程(7)OxyPlot框架
  4. 分享Kali Linux 2016.2第42周镜像文件
  5. 飞凌 修改ip地址 linux,linux上搭建DHCP服务
  6. java cdata xml 解析,如何解析lt;![CDATA []]gt;的XML
  7. iOS 滚动图滚动到顶部汇总
  8. ifconfig 安装_第一章Linux服务器环境搭建之JDK安装
  9. 怎么将两个datatable 合并_视频音频合并大师免费版-视频音频合并大师2020版下载(附使用方法) v2020.02.08...
  10. 脑电分析系列[MNE-Python-4]| MNE中数据结构Evoked及其对象创建