最近跟着(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的更多相关文章

  1. OpenGL学习笔记——求值器和NURBS

    http://codercdy.com/openglxue-xi-bi-ji-qiu-zhi-qi-he-nurbs/ 在最底层,图形硬件所绘制的是点.直线和多边形(通常是三角形和四边形).平滑的曲线 ...

  2. Aviator 表达式求值引擎开源框架

    简介¶ Aviator是一个高性能.轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值.现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢? Aviato ...

  3. JavaScript忍者秘籍——运行时代码求值

    1. 代码求值机制 JavaScript中,有很多不同的代码求值机制. ● eval()函数 ● 函数构造器 ● 定时器 ● <script>元素 - 用eval()方法进行求值 作为定义 ...

  4. 利用Z.Expressions.Eval表达式求值

    Z.Expression.Eval是一个开源的(OpenSource),可扩展的(Extensible),超轻量级(Super lightweight)的公式化语言解析执行工具包. 使用方法:1.从n ...

  5. Python学习总结17:exec和eval执行求值字符串

    有些时候可能会需要动态地创造Python代码,然后将其作为语句执行或作为表达式计算. 1. exec >>>exec "print 'Hello, world!'" ...

  6. Stream01 定义、迭代、操作、惰性求值、创建流、并行流、收集器、stream运行机制

    1 Stream Stream 是 Java 8 提供的一系列对可迭代元素处理的优化方案,使用 Stream 可以大大减少代码量,提高代码的可读性并且使代码更易并行. 2 迭代 2.1 需求 随机创建 ...

  7. 【Scheme】元循环求值

    #lang scheme (require rnrs/base-6) (require rnrs/mutable-pairs-6) (define (eval exp env) (cond ((sel ...

  8. [SICP] 求值规则

    在Java语言学习中,通常不太关注求值规则. (2+4*6)*(3+5+7)这样的组合式的求值规则.通常归结为优先级问题: if.for等的求值规则通常归结为语义. 函数式编程语言的Scheme,将这 ...

  9. 延迟求值-如何让Lo-Dash再提速x100?

    「注释」作者在本文里没有说明这么一个事实: 目前的版本Lo-Dash v2.4.1并没有引入延迟求值的特性,Lo-Dash 3.0.0-pre中部分方法进行了引入,比如filter(),map(),r ...

随机推荐

  1. Maven传递依赖的范围

    calsspath:仅加载本工程中的配置文件 classpath*:既要加载本工程中配置文件,也要加载jar包中的配置文件

  2. 【ASP.NET 问题】Win7中IIS被防火墙阻止导致外网无法访问的解决方法。

    今天装了IIS7.0,把网站发布了上去,但局域网的其他电脑始终无法访问主机上的网站. 于是想到防火墙的原因,把防火墙关掉,可以正常访问,但是打开就不行. 于是去网上找资料,总算搞定了. 原来在防火墙的 ...

  3. new date() 计算本周周一日期

    new date() 计算本周周一日期 需求:计算某天的那一周周一的日期 1.new Date() date.getDay(); //获取周几 0-6 date.getTime();//获取时间戳 1 ...

  4. 01.hadoop集群环境搭建

    hadoop集群搭建的步骤 1.安装jdk2修改ip地址3.关闭防火墙4.修改hostname5.设置ssh自动登陆6.安装hadoop-------------------------------- ...

  5. leetcode1022

    class Solution(object): def __init__(self): self.li = list() self.sums = 0 def Trace(self,root): if ...

  6. 线程池之 newScheduledThreadPool中scheduleAtFixedRate(四个参数)

    转自:https://blog.csdn.net/weixin_35756522/article/details/81707276 说明:在处理消费数据的时候,统计tps,需要用一个线程监控来获得tp ...

  7. crontab 安装与配置

    安装方法: yum -y install vixie-cron yum -y install crontabs 说明:vixie-cron 软件包是 cron 的主程序:crontabs 软件包是用来 ...

  8. elasticsearch-java

    elastissearch的JAVA客户端 官网  java api文档  https://www.elastic.co/guide/en/elasticsearch/client/java-api/ ...

  9. html _ 提取html片段内的纯文本

    var html = “html字符串”;var textstr =html.replace(/<[^>]*>|/g,"");//纯文本

  10. Oracle 学习总结 - 表和索引的性能优化

    表的性能 表的性能取决于创建表之前所应用的数据库特性,数据库->表空间->表,创建数据库时确保为每个用户创建一个默认的永久表空间和临时表空间并使用本地管理,创建表空间设为本地管理并且自动段 ...