Writing Files in Scheme

Here’s the translation of the Go code to Scheme, along with explanations in Markdown format suitable for Hugo:

Writing files in Scheme follows similar patterns to the ones we saw earlier for reading.

(import (chicken io)
        (chicken file)
        (chicken format))

(define (check e)
  (when e
    (error "An error occurred" e)))

; To start, here's how to dump a string (or just bytes) into a file.
(define d1 "hello\nscheme\n")
(check (with-output-to-file "/tmp/dat1" 
         (lambda () (display d1))
         #:mode 'text))

; For more granular writes, open a file for writing.
(define out (open-output-file "/tmp/dat2"))

; It's good practice to close the file after we're done with it.
(define (close-file)
  (close-output-port out))

; You can write strings as you'd expect.
(define d2 "some\n")
(define n2 (string-length d2))
(check (display d2 out))
(format #t "wrote ~A bytes\n" n2)

; Writing more strings is straightforward.
(define n3 (string-length "writes\n"))
(check (display "writes\n" out))
(format #t "wrote ~A bytes\n" n3)

; Flush writes to ensure they're written to the file.
(flush-output out)

; We can use with-output-to-file for buffered writes.
(define (buffered-write)
  (with-output-to-file "/tmp/dat2" 
    (lambda ()
      (display "buffered\n"))
    #:append))

(define n4 (string-length "buffered\n"))
(check (buffered-write))
(format #t "wrote ~A bytes\n" n4)

; Close the file
(close-file)

Try running the file-writing code:

$ csi -s writing-files.scm
wrote 5 bytes
wrote 7 bytes
wrote 9 bytes

Then check the contents of the written files:

$ cat /tmp/dat1
hello
scheme
$ cat /tmp/dat2
some
writes
buffered

In this Scheme version:

  1. We use with-output-to-file for simple file writes, which handles opening and closing the file automatically.

  2. For more granular control, we open a file with open-output-file and close it manually with close-output-port.

  3. We use display to write strings to the file.

  4. There’s no direct equivalent to WriteString in Scheme, as display handles both strings and other types.

  5. Instead of Sync, we use flush-output to ensure all buffered operations have been applied.

  6. For buffered writes, we use with-output-to-file with the #:append option to add to the existing file.

  7. Error handling is done with the check function, which raises an error if its argument is not false.

This example demonstrates basic file I/O operations in Scheme, showing how to write strings to files both directly and with buffering.