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到函数式编程的更多相关文章

  1. java8 array、list操作 汇【4】)- Java8 Lambda表达式 函数式编程

    int tmp1 = 1; //包围类的成员变量 static int tmp2 = 2; //包围类的静态成员变量 //https://blog.csdn.net/chengwangbaiko/ar ...

  2. python 函数对象(函数式编程 lambda、map、filter、reduce)、闭包(closure)

    1.函数对象 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 秉承着一切皆对象的理念,我们再次回头来看函数(function).函 ...

  3. Python函数式编程:Lambda表达式

    首先我们要明白在编程语言中,表达式和语句的区别. 表达式是一个由变量.常量.有返回值的函数加运算符组成的一个式子,该式子是有返回值的 ,如  a + 1 就是个表达式, 单独的一个常量.变量 或函数调 ...

  4. C# 函数式编程 —— 使用 Lambda 表达式编写递归函数

    最近看了赵姐夫的这篇博客http://blog.zhaojie.me/2009/08/recursive-lambda-expressions.html,主要讲的是如何使用 Lambda 编写递归函数 ...

  5. Java 中的函数式编程(Functional Programming):Lambda 初识

    Java 8 发布带来的一个主要特性就是对函数式编程的支持. 而 Lambda 表达式就是一个新的并且很重要的一个概念. 它提供了一个简单并且很简洁的编码方式. 首先从几个简单的 Lambda 表达式 ...

  6. 函数式编程--为什么会出现lambda表达式?

    java一直处在发张和演化的过程中,其中有2个版本从根本上改变了代码的编写方式.第一个就是JDK5之后增加的泛型,还有一个就是现在介绍的函数式编程,lambda表达式. lambda表达式是java8 ...

  7. Java函数式编程和lambda表达式

    为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...

  8. [学习] 从 函数式编程 到 lambda演算 到 函数的本质 到 组合子逻辑

    函数式编程 阮一峰 <函数式编程初探>,阮一峰是<黑客与画家>的译者. wiki <函数编程语言> 一本好书,<计算机程序的构造与解释>有讲到schem ...

  9. Java8函数式编程和lambda表达式

    文章目录函数式编程JDK8接口新特性函数接口方法引用函数式编程函数式编程更多时候是一种编程的思维方式,是一种方法论.函数式与命令式编程区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉 ...

随机推荐

  1. openCV学习笔记

    学习新玩意儿的事情,必须要懂人家的规矩,openCV就有自己的规范和数据结构的,要用人家的那些库函数,必须要把传入参数的基础结构搞搞明白,比如RGBA,人家opencv已经说了,用CvScalar,就 ...

  2. uvalive 4670 Dominating Patterns

    在文本串中找出现次数最多的子串. 思路:AC自动机模板+修改一下print函数. #include<stdio.h> #include<math.h> #include< ...

  3. 拉格朗日对偶(Lagrange duality)

    拉格朗日对偶(Lagrange duality) 存在等式约束的极值问题求法,比如下面的最优化问题:              目标函数是f(w),下面是等式约束.通常解法是引入拉格朗日算子,这里使用 ...

  4. 【Linux 命令】Linux系统下强制用户下线——who,pkill

    [日期]2014年11月18日 [平台]Centos 6.5 [工具]who pkill [步骤] 1)准备工作 以root身份登录. 2)执行who命令,查看有哪些用户已登录到当前主机

  5. C 头文件阅读理解

    __BEGIN_DECLS ..... ..... __END_DECLS 很多时候,为了使 C 代码和 C++ 代码保持互相兼容的过程调用接口,需要在 C++ 代码里加上 extern " ...

  6. SaltStack管理从这里开始

    Modules 1:查看所有module列表: salt 'jcfx-4' sys.list_modules jcfx-4: - acl - aliases - alternatives - apac ...

  7. [OC Foundation框架 - 2] NSString 的创建

    A. 不可变字符串 void stringCreate() { //Don't need to release memory by this way NSString *str1 = @"S ...

  8. IAR 1.3 for STM8 ST-Link无法调试 无法仿真 the debugging session could not be started

    IAR 1.3 for STM8 ST-Link无法调试 the debugging session could not be started CPU型号是:STM8F103F3 首先要用ST Vis ...

  9. [linux]发现一个vim的常用命令的图表,做的挺好,转过来

  10. 关于NoSQL数据库你应该知道的10件事

    关系数据库模型已经流行了几十年了,但是一种新类型的数据库——被称为NoSQL,正在引起企业的注意.下面是关于它的优势和劣势的一个概述.二十多年以来,对数据库管理来说,关系数据库(RDBMS)模型一直是 ...