The following get_file
function reads file from disk as a Scheme R6RS string:
; Gets all characters from a port
(define (read_chars_from_port_rev port result)
(let ((char (read-char port)))
(if (eof-object? char)
result
(read_chars_from_port_rev port (cons char result)))))
; Gets the contents of a file as a string
; If it doesn't exist, returns empty
(define (get_file file)
(if (file-exists? file)
(let ((port (open-input-file file)))
(let ((text (list->string (reverse (read_chars_from_port_rev port '())))))
(begin
(close-input-port port)
text)))
""))
It works by opening the file, tail-call-recursively reading char-by-char into a linked list until we find eof, closing the file, then reversing the linked list (because of the tail-call) and converting it to a string.
This procedure should be slow compared to, say, Node.js's readFile
, because it reads char by char, and allocates a linked list with one cell for each character in the file. Ideally, we should be able to just read a file as a string buffer, with no dynamic memory allocations.
Is there any way to optimize get_file
with the primitives available in R6RS?
You can use
get-string-all
:This can be made somewhat more convenient by using
call-with-input-file
:You can use
guard
to facilitate returning an empty string when the sought file does not exist (as in the posted code):