Ion Fusion Documentation
Release 0.38a1-SNAPSHOT (2026-04-16T19:45:37.790Z)

Module /fusion/io

Basic input/output features. At present these are generally Ion-oriented.

Reading Ion Data

The current Ion input port is an internal parameter that is the default source for reading Ion data. If it is not parameterized via one of the with_ion_from_* procedures, it is initialized from stdin when it's first needed.

The recommended way to consume a stream of Ion data is to use the in_port series in conjuction with a for comprehension. For example, to consume all remaining data on the current Ion input port into a list of top-level values, you can write:

(for_list [(v (in_port))]
  v)

Or, more directly:

(series_to_list (in_port))

The general comprehension pattern is valuable when you need to transform the data, since you can do it on-the-fly. For example, to extract the address fields from a document of structs:

(for_list [(v (in_port))]
  (. v "address"))

At a lower level than in_port, the read procedure produces one datum from the current port at a time, then a dedicated end-of-file marker. For example, to write (as Ion lines) those addresses to the current output port:

(let loop [(value (read))]
  (unless (is_eof value)
    (writeln (. value "address"))
    (loop (read))))

As you can see, read can be awkward when handling more than one datum, so it's usually better to use one of the series-orient approachs above. In this case, since we evoke side effects (printing) and don't need a result container, we can use for:

(for [(v (in_port))]
  (writeln (. value "address"))

The input port consumed by read and in_port can be "redirected" via procedures like with_ion_from_file, with_ion_from_lob, and with_ion_from_string, which parameterize the current input port for the duration of their invocation. For example, this procedure reads a file into a list of top-level values:

(define ion_file_to_list (path)
  (with_ion_from_file path
    (lambda ()
      (series_to_list (in_port)))))

Output

There are three "styles" of output:

These procedures render to the current output port, an internal parameter that's currently not accessible from this library, but that is configurable upon launch of the Fusion runtime. See FusionRuntimeBuilder for details.

current_directory procedure
(current_directory)

Returns the absolute path of the current working directory.

This is a parameter, so the value is thread-local and dynamically scoped via parameterize.

display procedure
(display value ...)

Outputs a text representation of the values to the current output port, in a form meant for human consumption. When a value is an unannotated string or symbol, its character data is written as-is, unquoted and unescaped. All other values are rendered as by write. No characters are written between the values. In general, the result will be unreadable by the Fusion and Ion readers.

display_to_string procedure
(display_to_string value ...)

Returns a string with a human-oriented text representation of the values. The output format is as defined by display.

displayln procedure
(displayln value ...)

Displays the values, then a newline.

eof constant

A unique value that denotes an end-of-file condition.

ionize procedure
(ionize value)

Outputs an Ion text representation of value to the current output port, throwing an exception if the value contains any non-Ionizable data like closures.

See write for an alternative that doesn't fail an non-Ionizable inputs.

ionize_to_blob procedure
(ionize_to_blob value)

Encodes an Ion binary representation of value, throwing an exception if the value contains any non-Ionizable data like closures. The result is a blob containing an Ion binary document.

ionize_to_string procedure
(ionize_to_string value)

Encodes an Ion text representation of value, throwing an exception if the value contains any non-Ionizable data like closures. The result is a string containing an Ion text document.

is_eof procedure
(is_eof value)

Determines whether a value is the Fusion end-of-file value. This value is bound to the name eof.

jsonize_to_string procedure
(jsonize_to_string value)

Encodes an JSON text representation of value, throwing an exception if the value contains any non-Ionizable data like closures. The result is a string containing a JSON text document.

Compared to ionize_to_string, this method applies these conversions:

  • All annotations are suppressed.
  • Nulls of any type are printed as JSON null.
  • Blobs are printed as strings, containing Base64.
  • Clobs are printed as strings, containing only Unicode code points U+00 through U+FF.
  • Sexps are printed as lists.
  • Symbols are printed as strings.
  • Timestamps are printed as strings, using Ion timestamp format.
read procedure
(read)

Reads an Ion value from the current Ion input port. Returns eof when there's no more data.

Here's one way to print to stdout the address fields of the structs on stdin:

(let loop [(value (read))]
  (unless (is_eof value)
    (writeln (. value "address"))
    (loop (read))))

In general, read is more low-level than necessary; see /fusion/io for more options.

with_ion_from_file procedure
(with_ion_from_file path thunk)

Opens the file at path and uses it as the current Ion input port while applying the thunk. The file is closed when the thunk returns (normally or abnormally).

The path must be a non-empty string denoting the file to read. If the path is relative, it is resolved against current_directory. The thunk must be a procedure that accepts zero arguments.

A common use of this procedure is to read the top-level Ion values from a file into a list:

(with_ion_from_file "path/to/file.ion"
  (|| (series_to_list (in_port))))

For other idioms, see /fusion/io.

with_ion_from_lob procedure
(with_ion_from_lob lob thunk)

Uses the content of lob (a blob or clob) as the current Ion input port while applying the thunk.

The lob must be non-null and may contain Ion text or binary data. The thunk must be a procedure that accepts zero arguments.

A common use of this procedure is to read a single Ion value from the data:

(with_ion_from_lob {{"[only_me]"}} read)   --> [only_me]

A common use of this procedure is to read the top-level Ion values from a lob into a list:

(with_ion_from_lob {{"[first] 2"}}   // Reading from a clob
  (|| (series_to_list (in_port))))
=>
[[first], 2]

For other idioms, see /fusion/io.

with_ion_from_string procedure
(with_ion_from_string string thunk)

Uses the content of string as the current Ion input port while applying the thunk.

The string must be non-null and must contain Ion text data. The thunk must be a procedure that accepts zero arguments.

A common use of this procedure is to read a single Ion value from the data:

(with_ion_from_string "123" read)   --> 123

This leverages the fact that read accepts zero arguments and consumes the current Ion input port. Note that this is likely to be more lenient than you wish, since the input is treated as a full Ion document:

(with_ion_from_string "$ion_1_0 123 /* ignored */" read)  --> 123

If more than one value is expected, you can read them all into a list:

(with_ion_from_string "1 k {a:false}"
  (|| (series_to_list (in_port))))
=>
[1, k, {a:false}]

For other idioms, see /fusion/io.

write procedure
(write value)

Outputs a text representation of value to the current output port, following Ion syntax where possible. The result will be unreadable (by the Fusion and Ion readers) if the value contains any non-Ionizable data like closures. Contrast this with ionize, which throws an exception in such cases.

writeln procedure
(writeln value)

Writes the value, then a newline.