这个解释器可以用来跑前面两篇文章的例子,所以一并扔出来,三部曲哈哈。

Lisp内置的S-expression相当于解析好的语法树,而借助quasiquote和unquote又很容易进行语法树层面的变换,所以Lisp的自举和扩展都很容易。

相对而言,其他语言有入门教材就讲怎么实现语言自身的解释器的吗?至少命令式语言恐怕不容易,尤其是中缀表示法的语言,Parser这一关会卡死很多人。

这个解释器的典型特性包括currying、call/cc,所以可以用来跑前面的lambda calculus和yin-yang-puzzle例子:

 #lang racket

 (require racket/match)
;------------------------------
(define (eval env e k)
(match e
[(? symbol?) (k (cdr (assq e env)))]
[(list 'lambda arg-list exp-list ...)
(let ([arg-list (if (empty? arg-list) '(_) arg-list)])
(cond
[(> (length arg-list) 1)
(eval env `(lambda (,(car arg-list)) (lambda ,(cdr arg-list) ,@exp-list)) k)]
[(> (length exp-list) 1)
(eval env `(lambda ,arg-list ((lambda (_) ,@(cdr exp-list)) ,(car exp-list))) k)]
[else (k
(lambda (arg k2)
(eval (cons (cons (car arg-list) arg) env) (car exp-list) k2)))]))]
[(list p arg-list ...)
(let ([arg-list (if (empty? arg-list) '(print) arg-list)])
(if (= 1 (length arg-list))
(eval env p (lambda (p)
(eval env (car arg-list) (lambda (arg)
(p arg k)))))
(eval env `((,p ,(car arg-list)) ,@(cdr arg-list)) k)))]
)
)
;------------------------------
(define G (list
(cons 'print (lambda (n k)
(n (lambda (v k2)
(k2 (add1 v)))
(lambda (v)
(v 0 (lambda (v) (k (print v))))))))
(cons 'newline (lambda (_ k)
(k (newline))))
(cons 'call/cc (lambda (f k)
(f (lambda (v k2) (k v)) k)))
))
;------------------------------
(eval G (read) identity)

用到了racket/match,当然,自己弄一个简单的linear pattern matcher也很容易,不过我就不做让事情复杂化的尝试了。

这是前文lambda calculus的例子,一字不变:

 ((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))(newline)) 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))
)

这是yin-yang-puzzle的例子,人肉展开了let*

 ((lambda (yin)
((lambda (yang)
(yin yang))
((lambda (c) (print (lambda (f x) x)) c)
(call/cc (lambda (k) k)))))
((lambda (c) (print (lambda (f x) (f x))) c)
(call/cc (lambda (k) k))))

[Scheme]一个Scheme的Metacircular evaluator的更多相关文章

  1. Scheme语言实例入门--怎样写一个“新型冠状病毒感染风险检测程序”

    小学生都能用的编程语言 2020的春季中小学受疫情影响,一直还没有开学,孩子宅在家说想做一个学校要求的研究项目,我就说你做一个怎么样通过编程来学习数学的小项目吧,用最简单的计算机语言来解决小学数学问题 ...

  2. 算法语言Scheme修订6报告 R6RS简体中文翻译

    算法语言Scheme修订6报告 R6RS简体中文翻译 来源 https://r6rs.mrliu.org/   MICHAEL SPERBERR. KENT DYBVIG, MATTHEW FLATT ...

  3. Android业务组件化之URL Scheme使用

    前言: 最近公司业务发展迅速,单一的项目工程不再适合公司发展需要,所以开始推进公司APP业务组件化,很荣幸自己能够牵头做这件事,经过研究实现组件化的通信方案通过URL Scheme,所以想着现在还是在 ...

  4. iOS - URL Scheme 操作

    推荐JLRoutes路由跳转 NSScanner 在寻找更加灵活的页面跳转和通知,我遇见了JLRoutes,从而学习使用URL Scheme来定义界面入口.以前从来没有使用过,不过很多大厂和流行的框架 ...

  5. 自定义 URL Scheme 完全指南

    本文由 Migrant 翻译自 The Complete Tutorial on iOS/iPhone Custom URL Schemes,转载请注明出处. 注意: 自从自定义 URL 的引入,本文 ...

  6. Project、Target、Workspace and Scheme

    前言 今天有人问我Target和Project是什么关系?额...学习iOS开发都知道Target和Project的关系.这里我就简单的做了一个总结,而且加入的Scheme和Workspace.如果不 ...

  7. 自定义 URL Scheme 完全指南(转载)

    iPhone / iOS SDK 最酷的特性之一就是应用将其自身”绑定”到一个自定义 URL scheme 上,该 scheme 用于从浏览器或其他应用中启动本应用. 注册自定义 URL Scheme ...

  8. URL Scheme APP跳转safari以及跳回APP

    上图 : 在plist文件里面设置. URL identifier 一般为反域名+项目名称 (尽可能保证少重复) URL Schemes是一个数组.一个APP可以添加多个.该参数为跳转时使用的标识. ...

  9. OpenCascade Tcl vs. ACIS Scheme

    OpenCascade Tcl vs. ACIS Scheme eryar@163.com 摘要Abstract:本文通过OpenCascade的Tcl/Tk和ACIS的Scheme的对比来说明脚本语 ...

随机推荐

  1. 【转】require.js学习笔记(二)

    require.js遵循AMD规范,通过define定义模块,require异步加载模块,一个js文件即一个模块. 一.模块加载require1.加载符合AMD规范模块 HTML: <scrip ...

  2. hdu 5748(求解最长上升子序列的两种O(nlogn)姿势)

    Bellovin Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepte ...

  3. QQ摄像头读取条码

    跟我学机器视觉-HALCON学习例程中文详解-QQ摄像头读取条码 第一步:插入QQ摄像头,安装好驱动(有的可能免驱动) 第二步:打开HDevelop,点击助手—打开新的Image Acquisitio ...

  4. 蛙蛙推荐:如何实时监控MySql状态

    大多网站的性能瓶颈都会出在数据库上,所以想把Mysql监控起来,就搜索了下相关资料. 后来和同事讨论了下cacti和nagios有些老套和过时,graphite比较时尚,然后就搜了下相关的资料,最后搞 ...

  5. 【转载】我也说 IEnumerable,ICollection,IList,List之间的区别

    做C#的同学们,都知道,一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 首先我看看 IEnumerable: / ...

  6. 通过git rebase修改commit message

    今天发现一个项目的git commit message中的单词拼错了,需要修改一下.但这样简单的修改,需要通过git rebase才能完成. 首先要git rebase到需要修改message的那个c ...

  7. 曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?

    很多刚入门的DBA在捕获阻塞得时候,会问这么一个问题“为什么这个SELECT语句被那个SELECT语句阻塞了,难道不是共享锁么?” 让我们来做个小测试,首先准备一些测试数据: --========== ...

  8. python __del__

    python __del__ 转自:http://blog.csdn.net/bbdxf/article/details/25774763 最近学习<Python参考手册>学到Class部 ...

  9. Windows Azure 使用体验

    本文只是对Windows Azure的肤浅使用做个记录,算是简单入门吧. 一.门户网站 Windows Azure其实有两个版本,我们在国内所说的或者说所用的就是有别于国际版的,主要原因我想各位也是知 ...

  10. JavaScript获取onclick、onchange等事件的值

    今天小菜处理下拉菜单级联问题时,想获取HTML标签中某个事件的内容,也就是值,比如从<select id="city" onchange="javascript:t ...