Racket:在函数中使用 "csv-reading" 包

Racket: Using "csv-reading" package within a function

我正在使用 csv-reading 读取 csv 文件并将其转换为列表。

当我在顶层调用时,像这样

> (call-with-input-file "to-be-asked.csv" csv->list)

我能够读取 csv 文件并将其转换为列表列表。

但是,如果我在一个函数中调用相同的东西,就会出现错误。

> (read-from-file "to-be-asked.csv")
csv->list: undefined;
 cannot reference an identifier before its definition
  in module: top-level

我不明白哪里出了问题。我在函数调用之前添加了 (require csv-reading)

我的read-from-file代码是:

(define (read-from-file file-name)
  (call-with-input-file file-name csv->list))

编辑

我在 emacs 中使用 racket 使用 Geiser。当我 (exit) 缓冲区并键入 C-c C-z 时,它显示错误。

当我终止缓冲区并再次启动 Geiser 时,它工作正常。 是不是Geiseremacs的错误?

您遇到了我称之为常驻编程环境的经典问题(当时我不知道合适的词)。 常驻编程环境 是您与语言的 运行 实例对话并连续修改其状态的环境。

这些环境的问题是 运行 语言实例的状态是 more-or-less 不透明的,特别是它可能与您在文件或缓冲区中看到的状态不同步。这意味着事情发生的原因可能会变得模糊不清,更糟糕的是,您可能会进入这样一种状态,即您从常驻环境中获得的结果以后基本上无法重现。这对于像 Jupyter notebooks 这样的东西来说非常重要,人们从事科学工作可能会得到他们无法重现的结果,因为 notebook 的评估顺序是乱序的,或者其中一些根本没有被评估。

另一方面,这些环境使用起来非常愉快,这就是我使用它们的原因。这对我来说比问题更重要:你只需要小心你可以重新创建会话并愿意偶尔这样做。

在这种情况下,您可能在 buffer/file:

中有类似的内容
(require csv-reading)

(define (read-from-file file-name)
  (call-with-input-file file-name csv->list))

但是您要么根本没有评估第一个表格,要么(更糟!)您评估表格的顺序不正确。如果您在 Common Lisp 或任何传统 Lisp 中执行此操作,一切都很好:评估第一种形式将使第二种形式起作用。但是球拍一劳永逸地决定 csv->list 在定义 read-from-file 时意味着什么(或不意味着什么),后来的 provide 不会解决这个问题。然后你最终会遇到你定义的函数不起作用的神秘情况,但是如果你定义一个使用 csv->listnew 函数,它 工作。这是因为它的语义比 CL 聪明得多,但据我所知,它的语义也不是为这种交互式开发设计的(当然 DrRacket 强烈反对它)。