首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跟踪递归计算器

跟踪递归计算器
EN

Stack Overflow用户
提问于 2016-07-25 03:45:02
回答 1查看 92关注 0票数 2

我用Moonscript Lua编写了一个简单的Lisp解释器。评估人员如下所示:

代码语言:javascript
复制
eval = ( env, expr ) ->
    if is_symbol expr
        lookup env, expr
    elseif is_define expr 
        eval_define env, expr
    elseif is_lambda expr 
        eval_lambda env, expr
    else call (map (partial eval, env), expr)

效果很好。但现在我真的很想找出这个过程,以类似于这样的方式:

代码语言:javascript
复制
(+ (+ a b) (+ a c))

(+ (+ 1 2) (+ 1 4))

(+ 3 5)

8

问题是,由于评估过程是递归的,所以在任何时候我都没有整个表达式要打印出来。

我是否必须以命令的方式重写评估器,还是遗漏了一些明显的东西?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-25 12:23:03

这个答案是使用Common,因为我并不真正了解Lua。

实际跟踪

通常,您希望跟踪代码中实际发生的情况。下面是对您的函数的重写,以及跟踪工具可以做什么的示例:

代码语言:javascript
复制
(defun normal-eval (form env)
  (etypecase form
    (cons (destructuring-bind (op . args) form
            (apply op
                   (mapcar (lambda (u)
                             (normal-eval u env))
                           args))))
    (null nil)
    (symbol (cdr (assoc form env)))
    (t form)))

> (trace normal-eval)
> (normal-eval '(+ (+ 1 3 a) 2) '((a . 5)))

0: (NORMAL-EVAL (+ (+ 1 3 A) 2) ((A . 5)))
  1: (NORMAL-EVAL (+ 1 3 A) ((A . 5)))
    2: (NORMAL-EVAL 1 ((A . 5)))
    2: NORMAL-EVAL returned 1
    2: (NORMAL-EVAL 3 ((A . 5)))
    2: NORMAL-EVAL returned 3
    2: (NORMAL-EVAL A ((A . 5)))
    2: NORMAL-EVAL returned 5
  1: NORMAL-EVAL returned 9
  1: (NORMAL-EVAL 2 ((A . 5)))
  1: NORMAL-EVAL returned 2
0: NORMAL-EVAL returned 11

期望跟踪

据我所知,在您提供的代码中,没有一种简单的方法可以获得所需的输出。但是,如果您愿意更改代码,则只需一步一步地重写术语,就可以以纯功能的方式获得所需的跟踪。但是,为了让表单逐渐改变,您必须防止对已经评估的术语进行评估。

代码语言:javascript
复制
(defun s-eval (x env)
  (etypecase x
    (cons (destructuring-bind (new-list . some-evalp)
              (reduce
               (lambda (element R)
                 (destructuring-bind (rec-list . some-evalp) R
                   (multiple-value-bind (value evalp) (s-eval element env)
                     (cons (list* value rec-list)
                           (or some-evalp evalp)))))
               (rest x)
               :from-end t
               :initial-value (cons nil nil))
            (values
             (if some-evalp
                 ;; a least one element required some work
                 ;; so we return the modified term. 
                 (cons (first x) new-list)
                 ;; all elements are literal, we can actually
                 ;; replace this form by its evaluation
                 (apply (first x) new-list))
             T)))
    (null (values nil nil))
    (symbol (values (cdr (assoc x env)) t))
    (t (values x nil))))

(defun step-eval (form &optional env)
  (print form)
  (multiple-value-bind (value evalp)
      (s-eval form env)
    (if evalp
        (step-eval value env)
        value)))

> (step-eval '(+ (+ 1 3 a) 2) '((a . 5)))


(+ (+ 1 3 A) 2) 
(+ (+ 1 3 5) 2) 
(+ 9 2) 
11


> (step-eval '(+ (+ 1 3 a) (* b a)) '((a . 5) (b . 0)))


(+ (+ 1 3 A) (* B A)) 
(+ (+ 1 3 5) (* 0 5)) 
(+ 9 0) 
9

> (step-eval '(+ (+ a b) (+ a c)) '((a . 1)
                                  (b . 2)
                                  (c . 4)))


(+ (+ A B) (+ A C)) 
(+ (+ 1 2) (+ 1 4)) 
(+ 3 5) 
8

S-EVAL在环境中计算表单,并返回两个值:表单的计算和指示某个计算是否实际发生或该术语是否为自评估(文字)的布尔值。此布尔值用于防止转换一个由递归计算转换子项的术语。STEP-EVAL打印表单并调用S-EVAL,然后递归地调用它自己,直到计算终止。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38559402

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档