Search code examples
csvemacsracketgeiser

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


I am using csv-reading to read from a csv file to convert it into a list.

When I call at the top level, like this

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

I am able to read csv file and convert it into list of lists.

However, if I call the same thing within a function, I am getting the error.

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

I am not getting what's going wrong. I have added (require csv-reading) before the function call.

My read-from-file code is:

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

EDIT

I am using racket within emacs using Geiser. When I (exit) the buffer and type C-c C-z, it is showing the error.

When I kill the buffer and start the Geiser again, it is working properly. Is it the mistake of Geiser and emacs?


Solution

  • You've hit the classic problem with what I'll call resident programming environments (I don't know the right word for then). A resident programming environment is one where you talk to a running instance of the language, successively modifying its state.

    The problem with these environments is that the state of the running language instance is more-or-less opaque and in particular it can get out of sync with the state you can see in files or buffers. That means that it can become obscure why something is happening and, worse, you can get into states where the results you get from the resident environment are essentially unreproducible later. This matters a lot for things like Jupyter notebooks where people doing scientific work can end up with results which they can't reproduce because the notebook was evaluated out of sequence or some of it was not evaluated at all.

    On the other hand, these environments are an enormous joy to use which is why I use them. That outweighs the problems for me: you just have to be careful you can recreate the session and be willing to do so occasionally.

    In this case you probably had something like this in the buffer/file:

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

    But you either failed to evaluate the first form at all, or (worse!) you evaluated the forms out of order. If you did this in Common Lisp or any traditional Lisp this would all be fine: evaluating the first form would make the second form work. But Racket decides once and for all what csv->list means (or does not mean) at the point the read-from-file is defined, and a later provide won't fix that. You then end up in the mysterious situation where the function you defined does not work, but if you define a new function which uses csv->list it will work. This is because it has much cleverer semantics than CL, but also semantics not designed for this kind of interactive development as far as I can tell (certainly DrRacket strongly discourages it).