加载定义值的文件会覆盖顶级绑定

时间:2011-08-08 17:06:47

标签: scheme

如果我有一个文件test.scm:

(define foo 5)

然后使用REPL:

(define foo 2)

foo
==> 2

(define bar
  (lambda ()
    (load "test.scm")
    foo))

foo
==> 2

(bar)
==> 5

foo
==> 5

换句话说,在一个词汇上下文中加载文件允许绑定转义到顶层。为什么会这样,有没有办法按照C #include包含另一个文件,即执行命令就好像它们在那时被拼接到代码中一样?

2 个答案:

答案 0 :(得分:2)

如果load执行的代码能够访问load表单的词汇上下文,则它不会是词汇上下文。

如果load是一个宏而不是一个函数,情况会有所不同 - 但即使这样,标准的R5RS宏也是卫生的,并且不容易弄乱词汇背景。

但是,您可以编写一个defmacro样式的宏,通过读取文件并返回包含从文件中读取的所有内容的begin表单来执行您所要求的内容。

示例代码:

(define-macro (include file)
  (let ((read-forms
         (lambda ()
           (let loop ((forms '()))
             (let ((form (read)))
               (if (eof-object? form)
                   (reverse forms)
                   (loop (cons form forms))))))))
    (with-input-from-file file
      (lambda ()
        (cons 'begin (read-forms))))))

请注意define-macro是非标准的。您必须确定是否以及如何使其工作,具体取决于您的Scheme实现。

答案 1 :(得分:1)

http://web.mit.edu/scheme_v9.0.1/doc/mit-scheme-user/Loading-Files.html

procedure: load filename [environment [syntax-table [purify?]]]

“环境,如果给出,则是评估文件的环境;如果没有,则使用当前的REPL环境。”

这意味着文件直接计算到repl而不是lambda闭包中。

修改 在SO (load "file.scm") in a New Environment in Scheme上看到这个问题如何建立新的环境。