从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接口新特性函数接口方法引用函数式编程函数式编程更多时候是一种编程的思维方式,是一种方法论.函数式与命令式编程区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉 ...
随机推荐
- shell文件/路径处理
#在此加上是不是目录的判断. if [ "`ls -A $dir`" = "" ]; then echo "$dir is empty" e ...
- HW6.10
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- Windows性能监视器之CPU、硬盘、IO等监控方法详解-摘自网络
一般操作系统性能主要涉及到的问题主要有:处理器使用情况.内存占有量.磁盘I/0操作以及网络流量等. 查看Windows性能情况,大部分情况下是通过 “Windows任务管理器”,可以通过在 ”命令行” ...
- POJ2723-Get Luffy Out(2-SAT)
题意:有m扇门,每个门上有两把锁,打开任意一个锁都可以打开这扇门.门要按顺序一个一个打开. 现在有n对不同的钥匙,每对钥匙只能用其中一个,问最多能打开多少门. 题解:对钥匙建图,门是限制条件来建边.每 ...
- Keil C51汉字显示的bug问题
一.缘起 这两天改进MCU的液晶显示方法,采用“即编即显”的思路,编写了一个可以直接显示字符串的程序.如程序调用disstr("我是你老爸");液晶屏上就会显示“我是你老爸”. 二 ...
- STM32 SysTick定时器应用【worldsing笔记】
SysTick是CM内核独立的定时器,时钟可以用内核内部的,也可以用芯片厂家(ST)的时钟,参考<Cortex-M3权威指南>的第13章: 另外也可以考<STM32F10xxx Co ...
- 低级错误之Hbm中类型不一致错误
Myeclipse将数据库中的长整形生成为Bigdecimal类型,实际应该生成为Long.导致保存的时候报错.
- VS2015开发环境配置
1.安装VS2015 Professional(专业版),按需勾选必要项(VC.C#.WEB.GIT) Visual Basic 2015 00322-50050-03552-AA642Microso ...
- C++学习笔记(十):类
类的定义: C++中使用关键字 class 来定义类, 其基本形式如下: class 类名 { public: //公共的行为或属性 protected: //受保护的行为或属性 private: / ...
- 两个简单方法加速DataGridView
两个简单方法加速DataGridView (2009-03-24 16:57:13) 转载▼ 标签: 杂谈 分类: .NET DataGridView虽然好用,但是如果数据量比较大的话就会出现性能的问 ...