10

假设我有一个像

#lang racket/base
(define (hello) (print "Hello"))
... more definitions ...

我想加载文件中的定义以在 (X)REPL 中交互地使用它们。我怎么做?

如果我启动 (X)REPL 和(load "/tmp/hello.rkt"),则该hello功能对我不可用:

-> (hello)
; hello: undefined;

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

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

注意我发现你如何通过命令行将文件加载到球拍中?,但这仅说明了如何运行该文件。不是如何在 REPL 中加载它,因此您可以测试/调试一些特定的定义,然后编辑、重新加载等。

4

2 回答 2

12

由于以模块开头的文件#lang,因此如果您使用它们,它什么也不做load。(实际上它做了一些事情,但可能对你没有帮助。)最好避免load完全使用,假装它不存在。

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

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

最后,您可能知道这一点,但与 DrRacket 一起工作通常会使事情变得更容易。

于 2013-02-16T18:06:20.880 回答
3

将 放在#lang racket/base文件顶部就是将文件标记为模块形式(这是#lang 简写);因此,加载文件只是为 . 添加模块定义(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 计划顶级无望”

于 2013-02-16T12:00:20.963 回答