是否有针对过程的Scheme toString方法?

时间:2014-04-11 18:54:24

标签: scheme racket tostring

我希望能够采取一个程序,看看它是什么样的。这可能吗?

例如,让我们说:

(define (some-func x)
  (+ x 1))

我想要做的是将一些神奇的功能(比如stringify)应用到some-func并且能够看到它的胆量。

\> (stringify some-func)
"(lambda (x) (+ x 1))"

我还没有找到任何可以做到这一点的Racket库。可以吗?!

2 个答案:

答案 0 :(得分:3)

在R6RS中,无法确定两个程序是否相同;即使像(let ((p (lambda () 42))) (eqv? p p))这样的表达也不能保证是真的。

R7RS通过使用“位置标记”的概念来解决这个问题,其中每个lambda表达式生成唯一的位置标记。然后eqv?通过比较位置标记来处理过程:因此(let ((p (lambda () 42))) (eqv? p p))为真,(eqv? (lambda () 42) (lambda () 42))为假。

没有可靠的方法来获取程序的来源(许多实现宏扩展和编译程序,丢弃原始来源),即使你可以,你也不能用它来比较两个程序是否是“等于“,因为闭包(并且两个程序可以具有相同的”源“但是它们的自由变量绑定到不同的东西)。例如,考虑两个表达式(let ((x 1)) (lambda () x))(let ((x 2)) (lambda () x))。他们拥有相同的“来源”,但正确思想中的任何人都不会声称他们在任何方面都是等同的。

答案 1 :(得分:0)

注意,您可以轻松实现define替代方案以保持来源。你没有避免词汇问题,但是,模数,你得到的东西用途有限。

(define name->source-mapping '())

(define (name->source name)
  (cond ((assq name name->source-mapping) => cdr)
        (else #f)))

(define (name->source-extend name source)
  (set! name->source-mapping (cons (cons name source) name->source-mapping))

(define-syntax define-with-source
  ((_ (name args ...) body1 body2 ...)
   (define name
     (begin (name->source-mapping-extend 'name '(lambda (args ...) body1 body2 ...))
                                             name->source-mapping))
            (lambda (args ...) body1 body2 ...)))))

[上面不替换(define name value)语法;仅考虑以上一个例子。]