notjack
2020-11-9 10:52:10

(this kind of confusion is why I think the only things that should be quoted are symbols, and quoting lists should be avoided)


phanthero
2020-11-9 14:50:22

Am I supposed to get an infinite loop when I set current-input-port to my-file? Just trying to learn the basics of file I/O in Racket #lang racket ;; Contents of <http://test1.in\|test1.in> ;; ( ;; ) ;; ra ;; ck ;; et (define my-file (open-input-file "<http://test1.in\|test1.in>")) (current-input-port my-file) (for ([i (in-lines)]) (println i)) (close-input-port my-file) "(" ")" "ra" "ck" "et" foo.rkt&gt; ; read-char: input port is closed foo.rkt&gt; ; read-char: input port is closed foo.rkt&gt; ; read-char: input port is closed ...


phanthero
2020-11-9 15:06:58

Also, I know that in C++ that you have cin cout cerr to refer to the standard streams stdin, stdout, stderr. How would you access these in Racket once you have set (current-input-port) , etc to something else?


badkins
2020-11-9 16:18:05

@phanthero current-input-port is a parameter, so maybe try something like this: #lang racket (define my-file (open-input-file "<http://test1.in\|test1.in>")) (parameterize ([ current-input-port my-file ]) (for ([i (in-lines)]) (println i))) (close-input-port my-file)


sorawee
2020-11-9 16:20:12

the problem here is that the REPL tries to use your closed port for getting more input.


sorawee
2020-11-9 16:20:51

So you should always restore current-input-port, or use parameterize as @badkins says (which is a better way)


phanthero
2020-11-9 16:24:36

@sorawee how do you restore current-input-port or current-error-port or current-output-port to stdin, stderr, stdout if you have set it to a file port ?


phanthero
2020-11-9 16:24:46

Also I guess I need to do some reading on what parameters are


sorawee
2020-11-9 16:25:30

Here’s one possibility:

(define orig-input-port (current-input-port)) (define my-file (open-input-file "<http://test1.in\|test1.in>")) (current-input-port my-file) (for ([i (in-lines)]) (println i)) (close-input-port my-file) (current-input-port orig-input-port)


sorawee
2020-11-9 16:26:34

The problem with the above approach is that if there’s an error before you reset it back, it won’t be reset back.


sorawee
2020-11-9 16:27:41

parameterize on the other hand will reset it back even when there’s an error.


samdphillips
2020-11-9 17:42:07

I tend to prefer call-with-input-file because you don’t end up messing with with the parameters, you can be explicit about where the input is coming from, and it disposes of the port for you when you leave the procedure.

In your case it’s probably easier to just pass my-file into in-lines , and not mess with any of the parameters.


phanthero
2020-11-9 19:27:53

@samdphillips I’m not sure I quite get it. From the documentation, as long as I understand correctly that for is a proc, this should work, but it isn’t unfortunately: #lang racket (call-with-input-file "<http://test1.in\|test1.in>" (for ([i (in-lines)]) (println i)))


soegaard2
2020-11-9 19:28:46

#lang racket (call-with-input-file "<http://test1.in\|test1.in>" (lambda () (for ([i (in-lines)]) (println i))))


sorawee
2020-11-9 19:29:58

@soegaard2 you meant with-input-from-file?


sorawee
2020-11-9 19:30:10

call-with-input-file needs a port argument


phanthero
2020-11-9 19:33:19

Yep, using with-input-from-file seems to solve it! Ok, so I guess for is categorized as a special form and not a procedure. I have the use-case that sometimes I want to read from a file and sometimes I want to read from stdin, so perhaps this might be better if I first conditionally defined an input port and passed that into a function instead of doing this. Thanks everyone.


phanthero
2020-11-9 19:38:35

The documentation uses thunk as a placeholder for the second argument for with-input-from-file etc, but proc as a placeholder for call-with-input-file etc. Is there a difference I need to know ?


soegaard2
2020-11-9 19:39:17

A thunk is a procedure of zero arguments. In practise: (lambda () body)


samdphillips
2020-11-9 21:05:32

I think you’ve gotten an answer, but here is how I would do it.

#lang racket (call-with-input-file "<http://test1.in\|test1.in>" (lambda (my-file) (for ([line (in-lines my-file)]) (println line))))