嗯,来写写经过:

在知乎上看见用Belleve牛用javascript写了一个精简的lisp解释器  

  =>

我也想写一个,用lua写,能多简单呢?  

  =>

写了一个阉割的scheme解释器,包含lambda/if两个special form,以及+-=print几个过程,60行代码  

  =>

能再精简吗?比如把if给去掉?  

  =>

搜索,嗯,lambda calculus能帮我  

  =>

阅读wiki上lambda calculus的"Encoding datatypes"部分  

  =>

改写scheme脚本,用Y-combinator帮助实现递归,用church numeral表示数字,以及实现church numeral之上的基本逻辑、算数、关系运算,最后用这些基本运算编写for-each和fib过程  

  =>

从解释器里移除关键字if,移除过程+-=,改写print过程使之能够打印church numeral

  =>

进一步把lambda实现为单参数过程,多参数lambda的声明和调用变成了语法糖,于是所有过程都是fully curried的了,和haskell一样

  =>

虽然scheme脚本为了打印fibonacci数列需要做更多的事情,但解释器仅仅为这门阉割scheme提供了一个lambda关键字;就结果而言,它演示了如何在只支持“匿名过程”这个基本元素的语言中实现强大的计算能力;当然,完成这一切靠的是lambda calculus理论。过程和结果都非常有趣~

scheme代码,只支持lambda这个special form和基本过程print:

 ((lambda (zero one add mul pow sub1 true false and or)
((lambda (sub not zero? two Y)
((lambda (less-equal? equal? three four)
;------------------------------
((lambda (for-each fib)
(for-each (lambda (i) (print (fib zero one zero i))) zero (mul four four))
)
(Y
(lambda (self)
(lambda (f i n)
(f i)
(((equal? i n)
(lambda () i)
(lambda () (self f (add i one) n))))
)
))
(Y
(lambda (self)
(lambda (a b i n)
(((equal? i n)
(lambda () a)
(lambda () (self b (add a b) (add i one) n))))
)
))
)
;------------------------------
)
(lambda (m n) (zero? (sub m n)))
(lambda (m n) (and (zero? (sub m n)) (zero? (sub n m))))
(add two one)
(add two two)
))
(lambda (m n) (n sub1 m))
(lambda (a) (a false true))
(lambda (n) (n (lambda (x) false) true))
(add one one)
(lambda (f)
((lambda (g) (g g))
(lambda (g) (f (lambda (a) ((g g) a))))))
))
(lambda (f x) x)
(lambda (f x) (f x))
(lambda (m n f x) (m f (n f x)))
(lambda (m n f) (m (n f)))
(lambda (e b) (e b))
(lambda (n f x)
(((n
(lambda (g h) (h (g f))))
(lambda (u) x))
(lambda (u) u)))
(lambda (a b) a)
(lambda (a b) b)
(lambda (a b) (a b a))
(lambda (a b) (a a b))
)

lua解释器代码:

 function S_parse(s)
s = string.gsub(s, ';[^\n]+\n', '')
s = string.gsub(s, '%s+', ',')
s = string.gsub(s, '[%(%)]', {['(']='{',[')']='}'})
s = string.gsub(s, '[^{},%d][^{},]*', '"%1"')
return assert(loadstring(string.format("return {%s}", s)))()[]
end
function S_lookupVar(vm, env, name)
while env do
if env[name] then return env[name] end
env = env[vm]
end
end
function S_createLambda(vm, env, argIdx, expArgs, expBody)
return function(arg)
local newEnv = {[vm]=env, [expArgs[argIdx]]=arg}
if argIdx == #expArgs then
for i = , #expBody - do S_interpret(vm, newEnv, expBody[i]) end
return S_interpret(vm, newEnv, expBody[#expBody])
else
return S_createLambda(vm, newEnv, argIdx + , expArgs, expBody)
end
end
end
function S_interpret(vm, env, exp)
if type(exp) == 'string' then
return S_lookupVar(vm, env, exp)
elseif exp[] == 'lambda' then
return S_createLambda(vm, env, , #exp[] > and exp[] or {'_'}, exp)
else
local p = S_interpret(vm, env, exp[])
for i = , math.max(#exp, ) do
p = p(exp[i] and S_interpret(vm, env, exp[i]) or nil)
end
return p
end
end
function S_createVM()
return {
G = {
['print'] = function(n) print(n(function(i) return i + end)()) end,
},
}
end
function S_eval(vm, s)
return S_interpret(vm, vm.G, S_parse(s))
end S_eval(S_createVM(), io.read('*a'))

驱动:

 #! /bin/bash
cat script.rkt | lua main.lua

结果:


源码放这儿:https://github.com/PublicScan/LambdaCalculus/tree/c4a64b162b7049a6d278c86aaaa4a7c0750d7fa7

[Lua]50行代码的解释器,用来演示lambda calculus的更多相关文章

  1. python爬虫实战:利用scrapy,短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...

  2. 50行代码实现python计算器主要功能

    实现功能:计算带有括号和四则运算的式子   3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 基本思路:使用正则表达式提取出每一层 ...

  3. 50行代码实现缓存,JAVA内存模型原理

    遇见这样的高人怎么办??下面是一个简单缓存的实现,相当牛叉!自己看吧,只有50行代码. 摘自:http://www.oschina.net/code/snippet_55577_3887 import ...

  4. HTML5游戏实战(1):50行代码实现正面跑酷游戏

    前段时间看到一个"熊来了"的HTML5跑酷游戏,它是一个典型的正面2D跑酷游戏,这里借用它来介绍一下用Gamebuilder+CanTK开发正面跑酷游戏的基本方法. CanTK(C ...

  5. 50行代码实现GAN | 干货演练

    2014年,Ian Goodfellow和他的同事发表了一篇论文,向世界介绍了生成对抗网络(GAN).通过对计算图和博弈论的创新性组合,他们表明如果有足够的建模能力,两个相互对抗的模型可以通过普通的反 ...

  6. 基于requirejs+bluebird,50行代码实现轻巧实用的前端CMD加载器

    首先是github地址,可以用git克隆命令也可以直接在git页面下载 https://github.com/kazetotori/js-requireAsync 下载下来后目录结构是这样的 -pac ...

  7. OpenCV图像识别初探-50行代码教机器玩2D游戏【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  8. 50行代码仿backbone_todos

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  9. 50行代码实现的高性能动画定时器 raf-interval

    写在前面 raf-interval 是基于 window.requestAnimationFrame() 封装的定时器. Github: https://github.com/dntzhang/raf ...

随机推荐

  1. 【转】Android studio 解决64K超出链接数限制问题

    http://my.oschina.net/gabriel1215/blog/602608 目录[-] 使用MultiDex支持库 注意事项 结论 如果你是一个android开发者,你至少听说过的Da ...

  2. 作死遇到的坑--view向下偏移

    好大一个坑.--谈谈view偏移问题: 先上张图, 图中白色部分.上面的是从网上找的资源.将导航栏隐藏之后用collectionView加上去而实现的滑动标签功能.开始以为是代码中的问题.然后仔细推敲 ...

  3. 【概念笔记】JavaEE - web part2

    IT`huhui前言录 续JavaEE - web part1 链接http://www.cnblogs.com/ithuhui/p/5930745.html, 持续修改更新. Cookie 1. 定 ...

  4. 打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数 其各位数字立方和等于该数本身。 例如:153是一个 "水仙花数 " 因为153=1*1*1+5*5*5+3*3*3

    for (int i = 100; i <= 999; i++) { int geWei, shiWei, baiWei; baiWei = i / 100; shiWei = (i - bai ...

  5. 利用扩展事件(Xevents)捕捉高消耗查询

    生产环境中有时需要使用者抓取一些特定的语句分析,如超超长查询,或高IO查询等.一般来说大家对跟踪比较熟悉,主要因为其有完善的UI支持.由于扩展事件在sql2012才提供UI支持,所以虽然在08时就已经 ...

  6. ASP.NET MVC学习之模型绑定(2)

    3.手工调用模型绑定 很多情况下我们都是通过形参的方式接收来自http流中的数据,这看似是完美的,但是缺少了很多过程中的控制,所以我们就需要使用手工的方式进行绑定.下面我们通过一个例子来说明,首先打开 ...

  7. C#函数式编程之缓存技术

    缓存技术 该节我们将分成两部分来讲解,第一部分为预计算,第二部分则为缓存.缓存这个技术对应从事开发的人员来说是非常熟悉的,从页面缓存到数据库缓存无处不在,而其最重要的特点就是在第一次查询后将数据缓存, ...

  8. Configuring Locales

    原文地址:http://people.debian.org/~schultmc/locales.html The Easy Way Install debconf (i.e. runapt-get u ...

  9. C#自定义控件

    在网络上看了许多文章,终于找到了让我入门的自定义控件文章,这是链接  https://msdn.microsoft.com/zh-cn/library/cc438236(v=vs.71).aspx   ...

  10. Atitit.人力资源管理原理与概论

    Atitit.人力资源管理原理与概论 1. 人力资源管理 第一章 人力资源管理概述 第二章 人力资源理论基础与发展演变 第三章 人力资源规划 第四章工作分析与工作设计 第五章 员工招聘与录用 第六章 ...