(rontolisp) docs
← cl Package Functions

read

(read &optional stream eof-error-p eof-value recursive-p)

Reads and parses a single S-expression. With no argument it reads from standard input; given a stream opened by open, with-open-file or with-input-from-string it reads from that stream. It consumes exactly the characters of one datum and leaves the stream positioned after them, so a second datum on the same line survives, a datum may span lines, and read mixes with read-line and read-char on the same stream. Whitespace and comments before the datum are skipped, and one whitespace character after it is consumed (the standard allows this); a terminating character such as ) is left in the stream. At end of input read signals end-of-file unless eof-error-p is explicitly nil (eof-error-p defaults to t); only then does it return eof-value (nil by default). An incomplete datum signals end-of-file whatever eof-error-p says, and a malformed datum signals reader-error. Both are error subtypes carrying the stream (stream-error-stream), so (handler-case ... (error () ...)) catches them on every backend; the compiled reader reports the same failures as a catchable simple-error, or reads a few malformed token shapes as symbols -- see Compiled read/load Limitations. The compiled backends emit a runtime reader with frontend parity: lists (dotted pairs included), ', #', strings, symbols, numbers (ratios and #x/#o/#b radix integers included), #\ character literals, #(...)/#nA(...) arrays, #* bit vectors, #f(/#d( packed float arrays, #S(...) structure literals and #|...|# block comments. A #+/#- guard is resolved by read itself on every backend, against *features* as it stands at the call: a guard that fails skips the form behind it and read answers the next datum (#+nope a b reads B), at top level and inside a list. #. and #n=/#n# need an evaluator at read time, so the compiled reader signals a catchable error on them (the interpreter still resolves them; binding *read-eval* to nil there makes #. signal instead, per the standard). The WASM reader's numbers are narrower (64-bit integers, decimal floats without exponents, static error messages) -- see Compiled read/load Limitations.

With no stream argument, read parses one datum from standard input: reading (+ 1 2) there yields the list (+ 1 2). At end of input read signals end-of-file; pass an explicit nil eof-error-p to get the eof-value instead. Symbols read at run time follow the reader's upcasing -- your symbols and the standard names alike upcase (there is no fold) -- identically on every backend.