Skip to content

Ports and I/O

Ports are Scheme's abstraction for I/O streams. Kaappi supports textual and binary ports backed by files, strings, or bytevectors. Available from (scheme base), (scheme read), and (scheme write).


Port Operations

current-input-port

Syntax: (current-input-port)

Returns the current default input port. This is initially the standard input stream. The value can be temporarily changed with with-input-from-file or parameterize.

kaappi> (port? (current-input-port))
;=> #t
kaappi> (input-port? (current-input-port))
;=> #t

See also: current-output-port, with-input-from-file


current-output-port

Syntax: (current-output-port)

Returns the current default output port. This is initially the standard output stream. The value can be temporarily changed with with-output-to-file or parameterize.

kaappi> (port? (current-output-port))
;=> #t
kaappi> (output-port? (current-output-port))
;=> #t

See also: current-input-port, current-error-port, with-output-to-file


current-error-port

Syntax: (current-error-port)

Returns the current default error port. This is initially the standard error stream. Unlike current-output-port, error output is typically unbuffered so diagnostic messages appear immediately.

kaappi> (port? (current-error-port))
;=> #t
kaappi> (output-port? (current-error-port))
;=> #t

See also: current-output-port


port?

Syntax: (port? obj)

Returns #t if obj is a port (input port, output port, or input/output port), and #f otherwise.

kaappi> (port? (current-input-port))
;=> #t
kaappi> (port? (open-input-string "hello"))
;=> #t
kaappi> (port? "not-a-port")
;=> #f

See also: input-port?, output-port?


input-port?

Syntax: (input-port? obj)

Returns #t if obj is an input port, and #f otherwise.

kaappi> (input-port? (current-input-port))
;=> #t
kaappi> (input-port? (open-input-string "hello"))
;=> #t
kaappi> (input-port? (current-output-port))
;=> #f

See also: output-port?, port?


output-port?

Syntax: (output-port? obj)

Returns #t if obj is an output port, and #f otherwise.

kaappi> (output-port? (current-output-port))
;=> #t
kaappi> (output-port? (open-output-string))
;=> #t
kaappi> (output-port? (current-input-port))
;=> #f

See also: input-port?, port?


textual-port?

Syntax: (textual-port? obj)

Returns #t if obj is a textual port (one that reads or writes characters and strings), and #f otherwise. Ports opened with open-input-file, open-output-file, open-input-string, and open-output-string are textual.

kaappi> (textual-port? (current-input-port))
;=> #t
kaappi> (textual-port? (open-input-string "hello"))
;=> #t

See also: binary-port?


binary-port?

Syntax: (binary-port? obj)

Returns #t if obj is a binary port (one that reads or writes bytes and bytevectors), and #f otherwise. Ports opened with open-binary-input-file and open-binary-output-file are binary.

kaappi> (binary-port? (current-input-port))
;=> #f
kaappi> (binary-port? (open-binary-input-file "/dev/null"))
;=> #t

See also: textual-port?


input-port-open?

Syntax: (input-port-open? port)

Returns #t if port is an input port that has not been closed, and #f otherwise. After calling close-port or close-input-port, this returns #f.

kaappi> (let ((p (open-input-string "hello")))
         (let ((before (input-port-open? p)))
           (close-port p)
           (list before (input-port-open? p))))
;=> (#t #f)

See also: output-port-open?, close-port


output-port-open?

Syntax: (output-port-open? port)

Returns #t if port is an output port that has not been closed, and #f otherwise. After calling close-port or close-output-port, this returns #f.

kaappi> (let ((p (open-output-string)))
         (let ((before (output-port-open? p)))
           (close-port p)
           (list before (output-port-open? p))))
;=> (#t #f)

See also: input-port-open?, close-port


File I/O

open-input-file

Syntax: (open-input-file filename)

Opens the file named by the string filename for reading and returns a textual input port. It is an error if the file does not exist or cannot be opened for reading.

kaappi> (let ((p (open-input-file "data.txt")))
         (let ((line (read-line p)))
           (close-port p)
           line))
;=> "first line of file"

See also: open-output-file, call-with-input-file, close-port


open-output-file

Syntax: (open-output-file filename)

Opens the file named by the string filename for writing and returns a textual output port. If the file already exists, its contents are truncated. If it does not exist, a new file is created.

kaappi> (let ((p (open-output-file "out.txt")))
         (write-string "hello" p)
         (close-port p))

See also: open-input-file, call-with-output-file, close-port


open-binary-input-file

Syntax: (open-binary-input-file filename)

Opens the file named by the string filename for reading in binary mode and returns a binary input port. It is an error if the file does not exist or cannot be opened for reading.

kaappi> (let ((p (open-binary-input-file "image.bin")))
         (let ((byte (read-u8 p)))
           (close-port p)
           byte))
;=> 137

See also: open-binary-output-file, open-input-file


open-binary-output-file

Syntax: (open-binary-output-file filename)

Opens the file named by the string filename for writing in binary mode and returns a binary output port. If the file already exists, its contents are truncated. If it does not exist, a new file is created.

kaappi> (let ((p (open-binary-output-file "out.bin")))
         (write-u8 255 p)
         (close-port p))

See also: open-binary-input-file, open-output-file


close-port

Syntax: (close-port port)

Closes port, releasing any associated resources. After closing, I/O operations on the port will raise an error. If port is already closed, close-port has no effect. The return value is unspecified.

kaappi> (let ((p (open-input-string "hello")))
         (close-port p)
         (input-port-open? p))
;=> #f

See also: close-input-port, close-output-port, call-with-port


close-input-port

Syntax: (close-input-port port)

Closes the input side of port. Equivalent to close-port for pure input ports. For input/output ports, only the input direction is closed. The return value is unspecified.

kaappi> (let ((p (open-input-string "hello")))
         (close-input-port p)
         (input-port-open? p))
;=> #f

See also: close-port, close-output-port


close-output-port

Syntax: (close-output-port port)

Closes the output side of port. Equivalent to close-port for pure output ports. For input/output ports, only the output direction is closed. Any buffered output is flushed before closing. The return value is unspecified.

kaappi> (let ((p (open-output-string)))
         (write-string "hello" p)
         (close-output-port p)
         (output-port-open? p))
;=> #f

See also: close-port, close-input-port, flush-output-port


file-exists?

Syntax: (file-exists? filename)

Returns #t if the file named by the string filename exists, and #f otherwise. Available from (scheme file).

kaappi> (file-exists? "/tmp")
;=> #t
kaappi> (file-exists? "/nonexistent")
;=> #f

See also: delete-file, open-input-file


delete-file

Syntax: (delete-file filename)

Deletes the file named by the string filename. It is an error if the file does not exist or cannot be deleted. The return value is unspecified. Available from (scheme file).

kaappi> (call-with-output-file "/tmp/test.txt"
         (lambda (p) (write-string "temp" p)))
kaappi> (file-exists? "/tmp/test.txt")
;=> #t
kaappi> (delete-file "/tmp/test.txt")
kaappi> (file-exists? "/tmp/test.txt")
;=> #f

See also: file-exists?


call-with-input-file

Syntax: (call-with-input-file filename proc)

Opens the file named by filename for reading, passes the resulting textual input port to proc, and returns the value returned by proc. The port is not automatically closed when proc returns -- use call-with-port if automatic closing is needed. Available from (scheme file).

kaappi> (call-with-input-file "data.txt"
         (lambda (p) (read-line p)))
;=> "first line of file"

See also: call-with-output-file, call-with-port, with-input-from-file


call-with-output-file

Syntax: (call-with-output-file filename proc)

Opens the file named by filename for writing, passes the resulting textual output port to proc, and returns the value returned by proc. The port is not automatically closed when proc returns. Available from (scheme file).

kaappi> (call-with-output-file "out.txt"
         (lambda (p) (write-string "hello, world" p)))

See also: call-with-input-file, call-with-port, with-output-to-file


call-with-port

Syntax: (call-with-port port proc)

Calls proc with port as its argument. When proc returns, the port is closed automatically. The value returned by proc is returned. This ensures the port is always closed, even if proc raises an exception.

kaappi> (call-with-port (open-input-string "hello")
         (lambda (p) (read-line p)))
;=> "hello"
kaappi> (let ((p (open-input-string "test")))
         (call-with-port p read-line)
         (input-port-open? p))
;=> #f

See also: call-with-input-file, close-port


with-input-from-file

Syntax: (with-input-from-file filename thunk)

Opens the file named by filename for reading and parameterizes current-input-port to the resulting port for the dynamic extent of the call to thunk. The port is closed when thunk returns. Procedures like read and read-line that default to current-input-port will read from this file. Available from (scheme file).

kaappi> (with-input-from-file "data.txt"
         (lambda () (read-line)))
;=> "first line of file"

See also: with-output-to-file, current-input-port, call-with-input-file


with-output-to-file

Syntax: (with-output-to-file filename thunk)

Opens the file named by filename for writing and parameterizes current-output-port to the resulting port for the dynamic extent of the call to thunk. The port is closed when thunk returns. Procedures like display and write that default to current-output-port will write to this file. Available from (scheme file).

kaappi> (with-output-to-file "out.txt"
         (lambda () (display "hello, world")))

See also: with-input-from-file, current-output-port, call-with-output-file


Textual Input

read

Syntax: (read) | (read port)

Reads and returns the next Scheme datum from port, which defaults to current-input-port. At end of input, returns the eof object. The datum is parsed according to Scheme's read syntax -- strings, numbers, lists, vectors, and so on are all recognized. Available from (scheme read).

kaappi> (read (open-input-string "(+ 1 2)"))
;=> (+ 1 2)
kaappi> (read (open-input-string "42"))
;=> 42
kaappi> (read (open-input-string ""))
;=> #<eof>

See also: read-line, read-char, eof-object?


read-char

Syntax: (read-char) | (read-char port)

Reads and returns the next character from port, which defaults to current-input-port. At end of input, returns the eof object. The character is consumed from the port.

kaappi> (read-char (open-input-string "hello"))
;=> #\h
kaappi> (read-char (open-input-string ""))
;=> #<eof>

See also: peek-char, read-line, read-string


peek-char

Syntax: (peek-char) | (peek-char port)

Returns the next character from port without consuming it. Successive calls to peek-char without an intervening read return the same character. At end of input, returns the eof object. The port defaults to current-input-port.

kaappi> (let ((p (open-input-string "abc")))
         (let ((c1 (peek-char p))
               (c2 (peek-char p))
               (c3 (read-char p)))
           (list c1 c2 c3)))
;=> (#\a #\a #\a)

See also: read-char, char-ready?


read-line

Syntax: (read-line) | (read-line port)

Reads and returns the next line of text from port as a string. The line terminator (newline or carriage return + newline) is consumed but not included in the result. At end of input, returns the eof object. The port defaults to current-input-port.

kaappi> (read-line (open-input-string "hello\nworld"))
;=> "hello"
kaappi> (let ((p (open-input-string "line1\nline2\n")))
         (list (read-line p) (read-line p) (read-line p)))
;=> ("line1" "line2" #<eof>)

See also: read-char, read-string, read


read-string

Syntax: (read-string k) | (read-string k port)

Reads and returns a string of at most k characters from port. If fewer than k characters remain before end of input, the returned string contains only those characters. At end of input with no characters read, returns the eof object. The port defaults to current-input-port.

kaappi> (read-string 3 (open-input-string "hello"))
;=> "hel"
kaappi> (read-string 10 (open-input-string "hi"))
;=> "hi"
kaappi> (read-string 3 (open-input-string ""))
;=> #<eof>

See also: read-line, read-char


char-ready?

Syntax: (char-ready?) | (char-ready? port)

Returns #t if a character is ready to be read from port without blocking, or if the port is at end of input. Returns #f if reading would block. The port defaults to current-input-port. For string ports, this always returns #t.

kaappi> (char-ready? (open-input-string "hello"))
;=> #t
kaappi> (char-ready? (open-input-string ""))
;=> #t

See also: peek-char, read-char


Textual Output

display

Syntax: (display obj) | (display obj port)

Writes obj to port in human-readable form. Strings are written without enclosing double quotes and without escaping special characters. Characters are written as if by write-char. Other types are written as by write. The port defaults to current-output-port. The return value is unspecified.

kaappi> (display "hello")
hello
kaappi> (display 42)
42
kaappi> (display '(1 2 3))
(1 2 3)
kaappi> (display #\a)
a

display vs write

display is for output intended for people -- strings appear without quotes. write is for output that can be read back by read -- strings appear with quotes. Compare: (display "hi") prints hi, while (write "hi") prints "hi".

See also: write, write-string, newline


write

Syntax: (write obj) | (write obj port)

Writes obj to port in machine-readable form. The output uses the same syntax accepted by read, so (read) applied to the output reproduces the original value (for types that have a read syntax). Strings are enclosed in double quotes with special characters escaped. The port defaults to current-output-port. The return value is unspecified. Available from (scheme write).

kaappi> (write "hello")
"hello"
kaappi> (write '(1 "two" #\3))
(1 "two" #\3)
kaappi> (write 42)
42

See also: display, write-shared, write-simple, read


write-shared

Syntax: (write-shared obj) | (write-shared obj port)

Like write, but detects shared structure and circular references in obj, outputting them with datum labels (#N= to define and #N# to reference). This guarantees that the output is finite even for circular structures and that shared substructure is preserved when read back. Available from (scheme write).

kaappi> (let ((x (list 1 2)))
         (write-shared (list x x)))
(#0=(1 2) #0#)
kaappi> (let ((x (list 1 2 3)))
         (set-cdr! (cddr x) x)
         (write-shared x))
#0=(1 2 3 . #0#)

See also: write, write-simple


write-simple

Syntax: (write-simple obj) | (write-simple obj port)

Like write, but does not detect or mark shared structure. If obj contains cycles, write-simple may loop forever. This is faster than write-shared when you know the data has no cycles. Available from (scheme write).

kaappi> (write-simple '(1 2 3))
(1 2 3)
kaappi> (write-simple "hello")
"hello"

See also: write, write-shared


write-char

Syntax: (write-char char) | (write-char char port)

Writes the character char to port. The port defaults to current-output-port. The return value is unspecified.

kaappi> (write-char #\A)
A
kaappi> (write-char #\newline)

See also: write-string, display, read-char


write-string

Syntax: (write-string string) | (write-string string port) | (write-string string port start) | (write-string string port start end)

Writes the characters of string from index start (inclusive) to end (exclusive) to port. The port defaults to current-output-port, start defaults to 0, and end defaults to the length of the string. The return value is unspecified.

kaappi> (write-string "hello")
hello
kaappi> (write-string "hello world" (current-output-port) 6)
world
kaappi> (write-string "hello world" (current-output-port) 0 5)
hello

See also: write-char, display


newline

Syntax: (newline) | (newline port)

Writes a newline character to port. The port defaults to current-output-port. Equivalent to (write-char #\newline port). The return value is unspecified.

kaappi> (begin (display "hello") (newline) (display "world") (newline))
hello
world

See also: display, write-char


flush-output-port

Syntax: (flush-output-port) | (flush-output-port port)

Flushes any buffered output for port to the underlying file or device. The port defaults to current-output-port. This is useful when you need output to appear immediately, for example when writing a prompt before reading input. The return value is unspecified.

kaappi> (display "Enter name: ")
kaappi> (flush-output-port)

See also: close-output-port, current-output-port


String Ports

open-input-string

Syntax: (open-input-string string)

Returns a textual input port that reads from string. This is useful for parsing Scheme data from strings or for testing I/O procedures without creating temporary files.

kaappi> (read (open-input-string "(+ 1 2)"))
;=> (+ 1 2)
kaappi> (read-line (open-input-string "hello\nworld"))
;=> "hello"
kaappi> (let ((p (open-input-string "abc")))
         (list (read-char p) (read-char p) (read-char p)))
;=> (#\a #\b #\c)

See also: open-output-string, open-input-file


open-output-string

Syntax: (open-output-string)

Returns a textual output port that accumulates its output in an internal buffer. The accumulated string can be retrieved with get-output-string. This is the standard pattern for building strings incrementally.

kaappi> (let ((p (open-output-string)))
         (write-string "hello" p)
         (write-char #\space p)
         (write-string "world" p)
         (get-output-string p))
;=> "hello world"

See also: get-output-string, open-input-string, open-output-file


get-output-string

Syntax: (get-output-string port)

Returns a string containing all characters written to port, which must be a string output port created by open-output-string. The port remains open and can continue to accumulate output. Each call returns the full accumulated string from the beginning.

kaappi> (let ((p (open-output-string)))
         (display "hello" p)
         (let ((s1 (get-output-string p)))
           (display " world" p)
           (let ((s2 (get-output-string p)))
             (list s1 s2))))
;=> ("hello" "hello world")

See also: open-output-string


eof-object?

Syntax: (eof-object? obj)

Returns #t if obj is the end-of-file object, and #f otherwise. The eof object is returned by read procedures when the end of input is reached. There is exactly one eof object.

kaappi> (eof-object? (read (open-input-string "")))
;=> #t
kaappi> (eof-object? (read-char (open-input-string "")))
;=> #t
kaappi> (eof-object? "")
;=> #f
kaappi> (eof-object? #f)
;=> #f

See also: eof-object, read, read-char


eof-object

Syntax: (eof-object)

Returns the end-of-file object. This is the same object returned by read procedures at the end of input. There is exactly one eof object, so it can be compared with eq?.

kaappi> (eof-object)
;=> #<eof>
kaappi> (eq? (eof-object) (read (open-input-string "")))
;=> #t
kaappi> (eof-object? (eof-object))
;=> #t

See also: eof-object?, read