求值器本质--eval&apply
最近跟着(How to Write a (Lisp) Interpreter (in Python))使用python实现了一个简易的scheme解释器。不得不说使用python这类动态语言实现不要太方便。
解释器的核心实际就是2个部分:
- eval 在环境里求值表达式
- apply 将一个过程应用于一组参数

eval、apply 这两个规则描述了求值过程的核心部分,这是任何解释器的基本循环。在这一循环中表达式在环境中的求值被规约到过程对实际参数的应用,而这种应用又被规约到新的表达式在新的环境中的求值,如此下去,直到下降到符号(其值可以在环境中找到)或者基本过程(它们可以直接应用)。
接着我又尝试使用c++实现,由于c++没有python那么方便的list,我定义了一个抽象基类Type,让各种表达式作为它的派生类。过程还算顺利,只是在对过程求值环境的处理上烦了迷糊。
例如:
(define x (lambda (a) (lambda (b c) (+ a b c))))
(define y (x 1))
(y 2 3)
求值(x 1)为求值 (lambda (a) (lambda (b c) (+ a b c))) 作用于1的结果,返回(lambda (b c) (+ a b c)),同时具有环境a=1这个过程。
接着求值(y 2 3),实际是求值过程(x 1)作用于2 3的结果,那么求值环境呢? 显然是当前的b=2,c=3再加上procedure所具有的环境a=1,而不是在求值这个表达式时的环境x=... , y=... 。
再来看递归:
(define factor (lambda (n) (* n (if (= n 1) 1 (factor (- n 1))))))
(factor 3)
求值(factor 3) 时,带着n=3 环境,接着求值内部的(factor (- n 1)) 带着n=2 (从左到右为从内到外部环境,优先选择左侧),直到环境为 n=1时,(factor 1)返回1,在上层环境为n=2因此(* n 1)返回2,然后就是正常的递归回溯了。
以上说的可能有些混乱,简言之,求值一个过程时,环境为参数环境+过程的环境而不是参数环境+求值时的环境。
目前实现的解释器还很简易,缺少很多必要功能。例如垃圾回收,尾递归优化等。总之继续努力吧(__) 嘻嘻……
参考代码:https://github.com/CknightX/Practice/tree/master/c%2B%2B/scheme-interpreter
求值器本质--eval&apply的更多相关文章
- OpenGL学习笔记——求值器和NURBS
http://codercdy.com/openglxue-xi-bi-ji-qiu-zhi-qi-he-nurbs/ 在最底层,图形硬件所绘制的是点.直线和多边形(通常是三角形和四边形).平滑的曲线 ...
- Aviator 表达式求值引擎开源框架
简介¶ Aviator是一个高性能.轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值.现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢? Aviato ...
- JavaScript忍者秘籍——运行时代码求值
1. 代码求值机制 JavaScript中,有很多不同的代码求值机制. ● eval()函数 ● 函数构造器 ● 定时器 ● <script>元素 - 用eval()方法进行求值 作为定义 ...
- 利用Z.Expressions.Eval表达式求值
Z.Expression.Eval是一个开源的(OpenSource),可扩展的(Extensible),超轻量级(Super lightweight)的公式化语言解析执行工具包. 使用方法:1.从n ...
- Python学习总结17:exec和eval执行求值字符串
有些时候可能会需要动态地创造Python代码,然后将其作为语句执行或作为表达式计算. 1. exec >>>exec "print 'Hello, world!'" ...
- Stream01 定义、迭代、操作、惰性求值、创建流、并行流、收集器、stream运行机制
1 Stream Stream 是 Java 8 提供的一系列对可迭代元素处理的优化方案,使用 Stream 可以大大减少代码量,提高代码的可读性并且使代码更易并行. 2 迭代 2.1 需求 随机创建 ...
- 【Scheme】元循环求值
#lang scheme (require rnrs/base-6) (require rnrs/mutable-pairs-6) (define (eval exp env) (cond ((sel ...
- [SICP] 求值规则
在Java语言学习中,通常不太关注求值规则. (2+4*6)*(3+5+7)这样的组合式的求值规则.通常归结为优先级问题: if.for等的求值规则通常归结为语义. 函数式编程语言的Scheme,将这 ...
- 延迟求值-如何让Lo-Dash再提速x100?
「注释」作者在本文里没有说明这么一个事实: 目前的版本Lo-Dash v2.4.1并没有引入延迟求值的特性,Lo-Dash 3.0.0-pre中部分方法进行了引入,比如filter(),map(),r ...
随机推荐
- Termux 详细安装
termnux安装方法 https://blog.csdn.net/u010475354/article/details/79675893 使用Termux把Android手机变成SSH服务器 htt ...
- EditText获取焦点
这三个属性必须同时设置: private EditText passwde = null; passwde.setFocusable(true); passwde.setFocusableInTouc ...
- 水仙花在python3在pycharm的实现
---恢复内容开始--- #方法一:#-*- coding: utf-8-*-while True: num = input("请输入一个三位数") num = int(num) ...
- 01.hadoop集群环境搭建
hadoop集群搭建的步骤 1.安装jdk2修改ip地址3.关闭防火墙4.修改hostname5.设置ssh自动登陆6.安装hadoop-------------------------------- ...
- css:自己实现一个带小图标的input输入框
有小图标的input输入框<input type="text" placeholder="输入手机号" style="background:ur ...
- Spring Cloud限流详解
转自:https://blog.csdn.net/tracy38/article/details/78685707 在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud ...
- UNITY2018 真机开启deepprofiling的操作
手机上运行游戏并开启deepprofiling的命令如下 命令一:adb shell am start -n com.szyh.YHP1.kaopu/com.szyh.YHP1.kaopu.MainA ...
- Haskell语言学习笔记(82)Extensible effects
安装 extensible-effects $ cabal install extensible-effects Installed extensible-effects-3.0.0.0 Extens ...
- linux shell 语法学习
文件比较运算符-e filename 如果 filename存在,则为真 [ -e /var/log/syslog ]-d filename 如果 filename为目录,则为真 [ -d /tmp/ ...
- [Shell]一张图知道Shell(图)