我正在使用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))
编辑
我在使用Geiser
的emacs
中使用racket
。当我(exit)
缓冲区并键入C-c C-z
时,它显示错误。
当我杀死缓冲区并再次启动Geiser
时,它工作正常。是Geiser
和emacs
的错误吗?
您已经遇到了我称之为常驻编程环境的经典问题(我不知道这个词的正确含义(。常驻编程环境是指与正在运行的语言实例对话,依次修改其状态的环境。
这些环境的问题是,运行的语言实例的状态或多或少是不透明的,尤其是它可能与您在文件或缓冲区中看到的状态不同步。这意味着,它可能会变得不清楚为什么会发生一些事情,更糟糕的是,你可能会进入这样的状态,你从居民环境中得到的结果在以后基本上是不可复制的。这对像Jupyter笔记本这样的东西很重要,在那里,从事科学工作的人最终可能会得到他们无法复制的结果,因为笔记本的评估顺序不对,或者其中一些根本没有评估。
另一方面,使用这些环境是一种巨大的乐趣,这就是我使用它们的原因。对我来说,这比问题更重要:你只需要小心,你可以重新创建会话,并愿意偶尔这样做。
在这种情况下,你可能在缓冲区/文件中有这样的东西:
(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->list
的新函数,它将起作用。这是因为它的语义比CL聪明得多,但据我所知,它的语义并不是为这种交互式开发而设计的(当然DrRacket强烈反对(。