如何(重新)加载Racket(X)REPL中的文件?

时间:2013-02-16 09:36:06

标签: load scheme racket read-eval-print-loop

假设我有一个像

这样的文件
#lang racket/base
(define (hello) (print "Hello"))
... more definitions ...

我希望在文件中加载定义,以便在(X)REPL中以交互方式使用它们。我该怎么做?

如果我启动(X)REPL和(load "/tmp/hello.rkt"),则我无法使用hello函数:

-> (hello)
; hello: undefined;

如果我(require (file "/tmp/hello.rkt")),结果是一样的。现在我可以 (enter! (file "/tmp/hello.rkt")),然后(hello)可以正常工作,但这似乎是......不直观且初学者不友好。

这确实是应该这样做的方式吗?我应该阅读模块和命名空间以轻松浏览和试验我的代码,还是有一种更简单的方法可以忽略?

N.B。我找到了How do you load a file into racket via command line?,但这只解释了如何运行文件。不是如何在REPL中加载它,所以你可以测试/调试一些特定的定义,然后编辑,重新加载等。

2 个答案:

答案 0 :(得分:10)

由于以#lang开头的文件是模块,因此如果您load它们则不会执行任何操作。 (实际上它做了一些事情,但可能不会对你有所帮助。)最好避免完全使用load,只是假装它不存在。

现在,使用require是正确的,但它的作用是实例化模块并让您访问它提供的名称。在您的情况下,您没有提供任何意味着您无法使用hello的内容。为此,您可以将(provide hello)添加到文件中。但这可能不是你想要的,因为你似乎想调试代码。 (即,您不希望provide来自您的模块的所有内容,只是为了处理事情。)

所以正确使用的是enter!,或者如果你正在使用xrepl,那么有一个更方便的,en命令。这将实例化模块并使repl使用模块的命名空间,因此您可以访问所有内容。 (并且您不需要loadrequire它。)如果您更改了代码,也可以多次使用它来重新加载代码。但请注意,它存在一些问题,因此您可能需要安装nightly build才能使用它。

最后,您可能知道这一点,但与DrRacket合作会让事情变得更容易。

答案 1 :(得分:3)

#lang racket/base放在文件的顶部将文件标记为模块形式(这是#lang shorthand);因此,加载文件只是添加(file "/tmp/hello.rkt")的模块定义,正如您在需要该路径时所发现的那样。

如果您只想尝试一组定义并尝试以交互方式加载它们,则可以尝试从文件顶部删除 #lang racket/base。我在这里用一对“Racket toplevel”(rktl)文件来说明这一点:

% cat hello-unhashed.rktl
(define (hello) (print "Hello") (newline))
% cat hello2-unhashed.rktl
(define (hello) (print "Hello2") (newline))
% racket
Welcome to Racket v5.3.2.
> (load "hello-unhashed.rktl")
> (hello)
"Hello"
> (load "hello2-unhashed.rktl")
> (hello)
"Hello2"
> (load "hello-unhashed.rktl")
> (hello)
"Hello"
> (exit)
% 

请注意,以上述方式在顶层工作时存在很多陷阱。为了感受我正在谈论的内容,尝试谷歌搜索“球拍顶级水平是绝望的”或“plt计划顶级水平是无望的”