[Scheme]一个Scheme的Metacircular evaluator
这个解释器可以用来跑前面两篇文章的例子,所以一并扔出来,三部曲哈哈。
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的更多相关文章
- Scheme语言实例入门--怎样写一个“新型冠状病毒感染风险检测程序”
小学生都能用的编程语言 2020的春季中小学受疫情影响,一直还没有开学,孩子宅在家说想做一个学校要求的研究项目,我就说你做一个怎么样通过编程来学习数学的小项目吧,用最简单的计算机语言来解决小学数学问题 ...
- 算法语言Scheme修订6报告 R6RS简体中文翻译
算法语言Scheme修订6报告 R6RS简体中文翻译 来源 https://r6rs.mrliu.org/ MICHAEL SPERBERR. KENT DYBVIG, MATTHEW FLATT ...
- Android业务组件化之URL Scheme使用
前言: 最近公司业务发展迅速,单一的项目工程不再适合公司发展需要,所以开始推进公司APP业务组件化,很荣幸自己能够牵头做这件事,经过研究实现组件化的通信方案通过URL Scheme,所以想着现在还是在 ...
- iOS - URL Scheme 操作
推荐JLRoutes路由跳转 NSScanner 在寻找更加灵活的页面跳转和通知,我遇见了JLRoutes,从而学习使用URL Scheme来定义界面入口.以前从来没有使用过,不过很多大厂和流行的框架 ...
- 自定义 URL Scheme 完全指南
本文由 Migrant 翻译自 The Complete Tutorial on iOS/iPhone Custom URL Schemes,转载请注明出处. 注意: 自从自定义 URL 的引入,本文 ...
- Project、Target、Workspace and Scheme
前言 今天有人问我Target和Project是什么关系?额...学习iOS开发都知道Target和Project的关系.这里我就简单的做了一个总结,而且加入的Scheme和Workspace.如果不 ...
- 自定义 URL Scheme 完全指南(转载)
iPhone / iOS SDK 最酷的特性之一就是应用将其自身”绑定”到一个自定义 URL scheme 上,该 scheme 用于从浏览器或其他应用中启动本应用. 注册自定义 URL Scheme ...
- URL Scheme APP跳转safari以及跳回APP
上图 : 在plist文件里面设置. URL identifier 一般为反域名+项目名称 (尽可能保证少重复) URL Schemes是一个数组.一个APP可以添加多个.该参数为跳转时使用的标识. ...
- OpenCascade Tcl vs. ACIS Scheme
OpenCascade Tcl vs. ACIS Scheme eryar@163.com 摘要Abstract:本文通过OpenCascade的Tcl/Tk和ACIS的Scheme的对比来说明脚本语 ...
随机推荐
- 【筛法求素数】【质因数分解】bzoj2721 [Violet 5]樱花
http://www.cnblogs.com/rausen/p/4138233.html #include<cstdio> #include<iostream> using n ...
- alt属性
也被称为alt text, 是当图片无法加载时显示的替代文本.alt属性对于盲人或视觉损伤的用户理解一幅图片中所描绘的内容非常重要,搜索引擎也会搜索alt属性. 简而言之,每一张图片都应该有一个alt ...
- day4----json的简单实用
json官方说明参见:http://json.org/ Python操作json的标准api库参考:http://docs.python.org/library/json.html 重要函数 编码:把 ...
- codeforces 429D
题意:给定一个数组你个数的数组a,定义sum(i, j)表示sigma(a[i],...a[j]),以及另外一个函数f(i, j) = (i - j)^2 + sum(i+1, j)^2 求最小的f( ...
- Beetl 1.25 发布,java模板引擎
Beetl 1.25 发布改进记录包括: Beetl支持同JS一样三元逻辑表达式,如: var c = a>1?’li’;’miao’; var d = b>1?:’ok’; ...
- Jquery最全过滤器总结
不管什么时候,总是有这么些时候:当我们使用jQuery的各种过滤器时,总是有那么几个记不牢,还要搜索一下或者翻翻手册!多少次想总结一下,最终都没总结,现在网上找到一篇总结的不错的,但是排版有点乱,本人 ...
- [学习笔记] Dispose模式
Dispose模式是.NET中很基础也很重要的一个模式,今天重新复习一下相关的东西并记录下来. 什么是Dispose模式? 什么时候我们该为一个类型实现Dispose模式 使用Dispose模式时应该 ...
- Lingo 做线性规划 - Game Thoery
Reference: <An Introduction to Management Science Quantitative Approaches to Decision Making, Rev ...
- ThreadLocal线程范围内的共享变量
模拟ThreadLocal类实现:线程范围内的共享变量,每个线程只能访问他自己的,不能访问别的线程. package com.ljq.test.thread; import java.util.Has ...
- baguetteBox.js响应式画廊插件(纯JS)
baguetteBox.js baguetteBox.js 是一个简单和易于使用lightbox纯JavaScript脚本,拥有图像放大缩小并带有相应的CSS3过度,并能在触摸屏等设备上完美展示. D ...