从lambda到函数式编程
Object.send(:remove_const,'TRUE')
Object.send(:remove_const,'FALSE') def to_integer(pro)
pro[-> n { n + 1 }][0]
end def to_boolean(pro)
pro[true][false]
end def to_array(l, count = nil)
array = []
until to_boolean(IS_EMPTY[l]) || count == 0
array.push FIRST[l]
l = REST[l]
count = count - 1 unless count.nil?
end
array
end def array_map_to_integer(my_list, count = nil)
to_array(my_list, count).map{ |p| to_integer(p) }
end def to_char(c)
to_integer(c).chr
end def to_string(s)
to_array(s).map{ |c| to_char(c) }.join
end def puts_strings(strs)
to_array(strs).each do |p|
puts to_string(p)
end
nil
end ZERO = -> p { -> x { x } }
ONE = -> p { -> x { p[x] } }
TWO = -> p { -> x { p[p[x]] } }
THREE = -> p { -> x { p[p[p[x]]] } } FIVE = -> p { -> x { p[p[p[p[p[x]]]]] } } FIFTEEN = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }
HUNDRED = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } } TRUE = -> x { -> y { x } }
FALSE = -> x { -> y { y } } IF = -> b { b } IS_ZERO = -> n { n[-> x { FALSE }][TRUE] } PAIR = -> x { -> y { -> f { f[x][y] } } }
LEFT = -> p { p[-> x { -> y { x } }] }
RIGHT = -> p { p[-> x { -> y { y } }] } INC = -> n { -> p { -> x { p[n[p][x]] } } } SLIDE = -> p { PAIR[RIGHT[p]][INC[RIGHT[p]]] }
DEC = -> n { LEFT[n[SLIDE][PAIR[ZERO][ZERO]]] } ADD = -> m { -> n { n[INC][m] } }
SUB = -> m { -> n { n[DEC][m] } }
MUL = -> m { -> n { n[ADD[m]][ZERO] } }
POW = -> m { -> n { n[MUL[m]][ONE] } } IS_LESS_OR_EQUAL =
-> m { -> n { IS_ZERO[SUB[m][n]] } } Z = -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }
MOD = Z[-> f { -> m { -> n {
IF[IS_LESS_OR_EQUAL[n][m]][
-> x {
f[SUB[m][n]][n][x]
}
][
m
]
} } }] DIV = Z[-> f { -> m { -> n {
IF[IS_LESS_OR_EQUAL[n][m]][
-> x {
INC[f[SUB[m][n]][n]][x]
}
][
ZERO
]
} } } ] EMPTY = PAIR[TRUE][TRUE]
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
IS_EMPTY= LEFT
FIRST = -> l { LEFT[RIGHT[l]] }
REST = -> l { RIGHT[RIGHT[l]] } PUSH = -> l { -> x {
FOLD[l][UNSHIFT[EMPTY][x]][UNSHIFT]
} } RANGE = Z[-> f {
-> m { -> n {
IF[IS_LESS_OR_EQUAL[m][n]][
-> x {
UNSHIFT[f[INC[m]][n]][m][x]
}
][
EMPTY
]
} }
}]
FOLD = Z[-> f {
-> l { -> x { -> g {
IF[IS_EMPTY[l]][
x
][
-> y {
g[f[REST[l]][x][g]][FIRST[l]][y]
}
]
} } }
}] MAP = -> k { -> f {
FOLD[k][EMPTY][
-> l { -> x { UNSHIFT[l][f[x]] } }
]
} } TEN = MUL[TWO][FIVE]
ASC_48 = MUL[MUL[THREE][INC[THREE]]][INC[THREE]]
ASC_65 = ADD[MUL[ADD[FIVE][ONE]][TEN]][FIVE]
CHAR_B = INC[ASC_65]
CHAR_F = ADD[ASC_65][FIVE]
CHAR_I = ADD[CHAR_F][THREE]
CHAR_U = ADD[CHAR_I][MUL[THREE][INC[THREE]]]
CHAR_Z = ADD[CHAR_U][FIVE] FIZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[EMPTY][CHAR_Z]][CHAR_Z]][CHAR_I]][CHAR_F]
BUZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[EMPTY][CHAR_Z]][CHAR_Z]][CHAR_U]][CHAR_B]
FIZZBUZZ= UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[BUZZ][CHAR_Z]][CHAR_Z]][CHAR_I]][CHAR_F] TO_DIGITS=
Z[-> f { -> n { PUSH[
IF[IS_LESS_OR_EQUAL[n][DEC[TEN]]][
EMPTY
][
-> x {
f[DIV[n][TEN]][x]
}
]
][ADD[MOD[n][TEN]][ASC_48]] } } ] SOLUTION=
MAP[RANGE[ONE][HUNDRED]][-> n {
IF[IS_ZERO[MOD[n][FIFTEEN]]][
FIZZBUZZ
][IF[IS_ZERO[MOD[n][THREE]]][
FIZZ
][IF[IS_ZERO[MOD[n][FIVE]]][
BUZZ
][
TO_DIGITS[n]
]]]
} ] ZEROS = Z[-> f { UNSHIFT[f][ZERO] }]
UPWARDS_OF = Z[-> f { -> n { UNSHIFT[-> x { f[INC[n]][x] }][n] } }]
MULTIPLES_OF =
-> m {
Z[-> f {
-> n { UNSHIFT[-> x { f[ADD[m][n]][x] }][n] }
}][m]
}
MULTIPLY_STREAMS =
Z[-> f {
-> k { -> l {
UNSHIFT[-> x { f[REST[k]][REST[l]][x] }][MUL[FIRST[k]][FIRST[l]]]
} }
}]
在λ演算中,每个表达式都代表一个函数,这个函数有一个参数,并且返回一个值。不论是参数和返回值,也都是一个单参的函数。可以这么说,λ演算中,只有一种“类型”,那就是这种单参函数。
在lambda演算中有许多方式都可以定义自然数,但最常见的还是邱奇数。
ZERO = -> p { -> x { x } }
ONE = -> p { -> x { p[x] } }
TWO = -> p { -> x { p[p[x]] } }
THREE = -> p { -> x { p[p[p[x]]] } } FIVE = -> p { -> x { p[p[p[p[p[x]]]]] } } FIFTEEN = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }
HUNDRED = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }
以此类推。直观地说,lambda演算中的数字n就是一个把函数f作为参数并以f的n次幂为返回值的函数。换句话说,邱奇整数是一个高阶函数 -- 以单一参数函数f为参数,返回另一个单一参数的函数。
习惯上,下述两个定义(称为邱奇布尔值)被用作TRUE和FALSE这样的布尔值:
TRUE = -> x { -> y { x } }
FALSE = -> x { -> y { y } }
“谓词”是指返回布尔值的函数。最基本的一个谓词是ISZERO,当且仅当其参数为零时返回真,否则返回假:
IS_ZERO = -> n { n[-> x { FALSE }][TRUE] }
运用谓词与上述TRUE和FALSE的定义,使得"if-then-else"这类语句很容易用lambda演算写出。
有序对(2-元组)数据类型可以用TRUE、FALSE和IF来定义。
PAIR = -> x { -> y { -> f { f[x][y] } } }
LEFT = -> p { p[-> x { -> y { x } }] }
RIGHT = -> p { p[-> x { -> y { y } }] }
链表数据类型可以定义为,要么是为空列表保留的值(e.g.FALSE),要么是CONS一个元素和一个更小的列表。
EMPTY = PAIR[TRUE][TRUE]
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
IS_EMPTY= LEFT
FIRST = -> l { LEFT[RIGHT[l]] }
REST = -> l { RIGHT[RIGHT[l]] }
递归是使用函数自身的函数定义;在表面上,lambda演算不允许这样。但是这种印象是误解。
使用Y组合子和Z组合子实现可以递归:
Z = -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }
从lambda到函数式编程的更多相关文章
- java8 array、list操作 汇【4】)- Java8 Lambda表达式 函数式编程
int tmp1 = 1; //包围类的成员变量 static int tmp2 = 2; //包围类的静态成员变量 //https://blog.csdn.net/chengwangbaiko/ar ...
- python 函数对象(函数式编程 lambda、map、filter、reduce)、闭包(closure)
1.函数对象 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 秉承着一切皆对象的理念,我们再次回头来看函数(function).函 ...
- Python函数式编程:Lambda表达式
首先我们要明白在编程语言中,表达式和语句的区别. 表达式是一个由变量.常量.有返回值的函数加运算符组成的一个式子,该式子是有返回值的 ,如 a + 1 就是个表达式, 单独的一个常量.变量 或函数调 ...
- C# 函数式编程 —— 使用 Lambda 表达式编写递归函数
最近看了赵姐夫的这篇博客http://blog.zhaojie.me/2009/08/recursive-lambda-expressions.html,主要讲的是如何使用 Lambda 编写递归函数 ...
- Java 中的函数式编程(Functional Programming):Lambda 初识
Java 8 发布带来的一个主要特性就是对函数式编程的支持. 而 Lambda 表达式就是一个新的并且很重要的一个概念. 它提供了一个简单并且很简洁的编码方式. 首先从几个简单的 Lambda 表达式 ...
- 函数式编程--为什么会出现lambda表达式?
java一直处在发张和演化的过程中,其中有2个版本从根本上改变了代码的编写方式.第一个就是JDK5之后增加的泛型,还有一个就是现在介绍的函数式编程,lambda表达式. lambda表达式是java8 ...
- Java函数式编程和lambda表达式
为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...
- [学习] 从 函数式编程 到 lambda演算 到 函数的本质 到 组合子逻辑
函数式编程 阮一峰 <函数式编程初探>,阮一峰是<黑客与画家>的译者. wiki <函数编程语言> 一本好书,<计算机程序的构造与解释>有讲到schem ...
- Java8函数式编程和lambda表达式
文章目录函数式编程JDK8接口新特性函数接口方法引用函数式编程函数式编程更多时候是一种编程的思维方式,是一种方法论.函数式与命令式编程区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉 ...
随机推荐
- openvpn文本验证模式配置
证书模式要为每个客户端生成一个证书,虽说安全性较好,但是比较麻烦,可以配置成用户名/密码的验证模式,这样就比较方便了,我这里用最简单的文本验证模式. 一.安装openvpn 不多说了,之前有篇文章已经 ...
- OpenCV中的矩阵乘法运算
转载:http://blog.csdn.net/tangwei2014 OpenCV中矩阵乘法运算 1. Mat*Mat: 第一个矩阵的列数必须等于第二个矩阵的行数. [0, 1, 2, 3; ...
- leetcode@ [139/140] Word Break & Word Break II
https://leetcode.com/problems/word-break/ Given a string s and a dictionary of words dict, determine ...
- HDU4276 - The Ghost Blows Light(树形DP)
题目大意 给定一棵n个结点的树,每个结点上有一定数量的treasure,经过每条边需要花一定的时间,要求你从结点1出发,在不超过时间T的情况下,最多能够获得的treasure是多少,并且要求结束于结点 ...
- android AudioRecord 与 AudioTrack的录音加回放的使用
http://stackoverflow.com/questions/32682952/audiotrack-audiotack-not-playing-fully-recorded-audio
- stm32 堆和栈(stm32 Heap & Stack)【worldsing笔记】
关于堆和栈已经是程序员的一个月经话题,大部分有是基于os层来聊的. 那么,在赤裸裸的单片机下的堆和栈是什么样的分布呢?以下是网摘: 刚接手STM32时,你只编写一个 int main() ...
- 射频识别技术漫谈(8)——动物标签【worldsing笔记】
动物标签也是工作在TTF模式的ID(Identification)卡.之所以通常称为动物标签,估计是因为一来和识别人的ID卡相区分,二是因为动物不如人听话,人的ID卡可以做成卡片形状拿在手上,而动物不 ...
- SpringMVC(一)
开始学习SpringMVC了,就写下每次学习的内容,以及自己的理解.方便以后回顾知道自己哪里好哪里不好~~~ 一.目录 1.主目录如此: 2.target目录 二.文件 1.主要用到的几个文件夹(如主 ...
- function和感叹号,运算符号的转化
1.下面的程序经过运算之后,a为true,这个很好理解,但是函数怎么会运行呢? var a = !function(){ alert('message'); }(); console.log(a); ...
- 智能电视TV开发---客户端和服务器通信
在做智能电视应用的时候,最头疼的就是焦点问题,特别是对于个人开发者,没有设备这是最最头疼的事情了,在没有设备的情况下,怎么实现智能电视应用呢,接下来我是用TV程序来做演示的,所以接下来的所有操作是在有 ...