(this kind of confusion is why I think the only things that should be quoted are symbols, and quoting lists should be avoided)
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> ; read-char: input port is closed
foo.rkt> ; read-char: input port is closed
foo.rkt> ; read-char: input port is closed
...
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?
@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)
the problem here is that the REPL tries to use your closed port for getting more input.
So you should always restore current-input-port
, or use parameterize
as @badkins says (which is a better way)
@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 ?
Also I guess I need to do some reading on what parameters are
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)
The problem with the above approach is that if there’s an error before you reset it back, it won’t be reset back.
parameterize
on the other hand will reset it back even when there’s an error.
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.
@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)))
#lang racket
(call-with-input-file "<http://test1.in\|test1.in>"
(lambda ()
(for ([i (in-lines)])
(println i))))
@soegaard2 you meant with-input-from-file
?
call-with-input-file
needs a port argument
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 define
d an input port and passed that into a function instead of doing this. Thanks everyone.
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 ?
A thunk is a procedure of zero arguments. In practise: (lambda () body)
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))))