【问题标题】:Racket: Using "csv-reading" package within a functionRacket:在函数中使用“csv-reading”包
【发布时间】:2021-01-05 05:59:15
【问题描述】:

我正在使用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的错吗?

【问题讨论】:

  • 你在哪里写的? (require csv-reading) 它应该在文件的顶部
  • 是的,它在顶部。事实上,这是我在 REPL 中的第一个声明。我想,这是Emacs 中的Geiser 实现的问题。请参考我的编辑。

标签: csv emacs racket geiser


【解决方案1】:

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

这些环境的问题在于,正在运行的语言实例的状态或多或少是不透明的,特别是它可能与您在文件或缓冲区中看到的状态不同步。这意味着它可能会变得晦涩难懂,更糟糕的是,您可能会进入从常驻环境中获得的结果在以后基本上无法重现的状态。这对于像 Jupyter notebook 这样的东西来说很重要,在这种情况下,从事科学工作的人最终可能会得到他们无法重现的结果,因为 notebook 的评估顺序不正确,或者其中一些根本没有评估。

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

在这种情况下,您可能在缓冲区/文件中有类似的内容:

(require csv-reading)

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

但是您要么根本没有评估第一个表单,要么(更糟糕的是!)您对表单进行了无序评估。如果你在 Common Lisp 或任何传统的 Lisp 中这样做,这一切都很好:评估第一种形式将使第二种形式工作。但是 Racket 在定义 read-from-file 时一劳永逸地决定了 csv->list 的含义(或不意味着),而后来的 provide 不会解决这个问题。然后你会陷入你定义的函数不起作用的神秘情况,但是如果你定义一个使用csv->listnew 函数,它 工作。这是因为它具有比 CL 更聪明的语义,但据我所知,它还具有并非为这种交互式开发设计的语义(当然 DrRacket 强烈反对它)。

【讨论】:

  • 太棒了!!!。感谢您的超级答案。这对我来说是一个很大的学习。
猜你喜欢
  • 1970-01-01
  • 2016-12-25
  • 2017-10-14
  • 2020-04-09
  • 2016-04-23
  • 2013-08-05
  • 2011-12-26
  • 1970-01-01
  • 2016-07-17
相关资源
最近更新 更多