求值器本质--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 ...
随机推荐
- ubuntu 使用sudo apt-get update命令的时候会报http://archive.ubuntukylin.com:10006/ubuntukylin/dists/xenial/InRelease 无法连接
参考: https://blog.csdn.net/xiaoyan94/article/details/52404539 于是找到一个包含 http://archive.ubuntukylin.co ...
- WDA-Web Dynpro的POWL(个人对象工作清单)
POWL(Personal Object Worklist) for Web Dynpro 转载地址:https://blogs.sap.com/2013/02/15/powlpersonal-obj ...
- 01_hello world
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 页面中的checkbox多选值获取
依据name名称获取选中值 var arr=document.getElementsByName("name");arr是一个数组,就是所有checkbox的值:for(i=0;i ...
- mui 常用手势
一 事件: 点击:1. tap 单击屏幕2. doubletap 双击屏幕长按:1. longtap 长按屏幕2. hold 按住屏幕3.release 离开屏幕滑动:1. swipeleft 向左滑 ...
- CSS DISPLAY AND POSITIONING
CSS DISPLAY AND POSITIONING Review: Layout Great job! In this lesson, you learned how to control the ...
- C++17尝鲜:变长 using 声明
using 声明 先来看 using 声明在类中的应用: 代码1 #include <iostream> using namespace std; struct A { void f(in ...
- 正则表达式(Kotlin)
课题 使用正则表达式匹配字符串 使用正则表达式 "\d{3}-(\d{4})-\d{2}" 匹配字符串 "123-4567-89" 返回匹配结果:'" ...
- C# winform进度条 (异步)
进度条页面: http://www.cnblogs.com/Deckard/archive/2009/06/24/1510451.html //============================ ...
- 拓展jquery js动态添加html代码 初始化数据
1 /** * 新增数据筛选 */ (function () { $.filterEvent = function(options){ var _this = this; var defaults = ...