Console I/O¶
Console input and output operations for interacting with standard streams.
Import¶
use <io/stdio>
Overview¶
The console I/O module provides functions for reading from standard input (stdin) and writing to standard output (stdout) and standard error (stderr). All console operations are built-in and don't require explicit imports, but stdin/stdout/stderr stream methods require use <io/stdio>.
Console Output¶
println¶
Print a message with a newline.
fn println(string message) -> ~
Parameters:
- message - String to print
Example:
fn main() i32:
println("Hello, World!")
println("Multiple lines")
println("work perfectly")
return Result.Ok(0)
String interpolation:
fn main() i32:
let string name = "Arthur"
let i32 age = 42
println("Hello, {name}!")
println("{name} is {age} years old")
return Result.Ok(0)
print¶
Print a message without a newline.
fn print(string message) -> ~
Parameters:
- message - String to print
Example:
fn main() i32:
print("Loading")
print(".")
print(".")
print(".")
println(" Done!")
return Result.Ok(0)
Output: Loading... Done!
Progress indicators:
use <time>
fn main() i32:
let i32 total = 10
foreach(i in 0..total):
print("*")
msleep(100 as i64)??
println("")
println("Complete!")
return Result.Ok(0)
Standard Streams¶
stdin¶
Read input from standard input.
stdin.readln¶
Read a line from stdin (blocks until newline).
fn stdin.readln() -> string
Returns: - String containing the line (without newline character)
Example:
use <io/stdio>
fn main() i32:
println("Enter your name:")
let string name = stdin.readln()
println("Hello, {name}!")
return Result.Ok(0)
Interactive prompt:
use <io/stdio>
use <collections/strings>
fn main() i32:
println("Enter your age:")
let string age_str = stdin.readln()
match age_str.to_i32():
Maybe.Some(age) ->
if (age >= 18):
println("You are an adult")
else:
println("You are a minor")
Maybe.None() ->
println("Invalid age")
return Result.Ok(0)
stdin.read_bytes¶
Read exactly N bytes from stdin.
fn stdin.read_bytes(i32 n) -> u8[]
Parameters:
- n - Number of bytes to read
Returns: - Byte array of length N
Example:
use <io/stdio>
fn main() i32:
println("Enter 4 bytes:")
let u8[] data = stdin.read_bytes(4)
println("Read {data.len()} bytes")
foreach(byte in data.iter()):
println("Byte: {byte}")
return Result.Ok(0)
Binary data:
use <io/stdio>
fn main() i32:
# Read a fixed-size header
let u8[] header = stdin.read_bytes(16)
# Process header bytes
let string text = header.to_string()
println("Header: {text}")
return Result.Ok(0)
stdout¶
Write to standard output.
stdout.write_bytes¶
Write raw bytes to stdout.
fn stdout.write_bytes(u8[] data) -> ~
Parameters:
- data - Byte array to write
Example:
use <io/stdio>
fn main() i32:
let u8[] data = from([72 as u8, 101 as u8, 108 as u8, 108 as u8, 111 as u8])
stdout.write_bytes(data)
println("") # Newline
return Result.Ok(0)
Output: Hello
Binary output:
use <io/stdio>
use <collections/strings>
fn main() i32:
# Write UTF-8 encoded text
let string text = "Hello, World!"
let u8[] bytes = text.to_bytes()
stdout.write_bytes(bytes)
return Result.Ok(0)
stderr¶
Write to standard error.
stderr.write_bytes¶
Write raw bytes to stderr.
fn stderr.write_bytes(u8[] data) -> ~
Parameters:
- data - Byte array to write
Example:
use <io/stdio>
use <collections/strings>
fn main() i32:
let string error = "ERROR: Something went wrong\n"
let u8[] error_bytes = error.to_bytes()
stderr.write_bytes(error_bytes)
return Result.Ok(1)
Error logging:
use <io/stdio>
use <collections/strings>
fn log_error(string message) ~:
let string formatted = "[ERROR] {message}\n"
let u8[] bytes = formatted.to_bytes()
stderr.write_bytes(bytes)
return Result.Ok(~)
fn main() i32:
log_error("Invalid configuration")??
log_error("Failed to connect")??
return Result.Ok(1)
Combining Streams¶
Redirecting output¶
Shell redirection works as expected:
# Redirect stdout to file
./program > output.txt
# Redirect stderr to file
./program 2> errors.txt
# Redirect both
./program > output.txt 2> errors.txt
# Redirect stderr to stdout
./program 2>&1
# Pipe stdout to another program
./program | grep "pattern"
Example: Logging with levels¶
use <io/stdio>
use <collections/strings>
fn log_info(string message) ~:
println("[INFO] {message}")
return Result.Ok(~)
fn log_error(string message) ~:
let string formatted = "[ERROR] {message}\n"
let u8[] bytes = formatted.to_bytes()
stderr.write_bytes(bytes)
return Result.Ok(~)
fn main() i32:
log_info("Starting application")??
log_info("Processing data")??
log_error("Failed to open file")??
log_info("Application finished")??
return Result.Ok(1)
Run with:
./program > info.log 2> error.log
Buffering Behavior¶
stdout buffering¶
Standard output is line-buffered when connected to a terminal:
- println() flushes immediately (contains newline)
- print() may be buffered until newline or buffer fills
fn main() i32:
# This appears immediately
println("Immediate")
# This may be buffered
print("Buffered")
# Force flush with newline
println("")
return Result.Ok(0)
stderr buffering¶
Standard error is unbuffered for immediate error visibility:
use <io/stdio>
use <collections/strings>
fn main() i32:
# Appears immediately, even without newline
let u8[] bytes = "Error".to_bytes()
stderr.write_bytes(bytes)
return Result.Ok(1)
Unicode Support¶
All console operations support UTF-8 encoded text:
fn main() i32:
println("Hello, World! 🌍")
println("Café")
println("日本語")
println("Привет")
return Result.Ok(0)
See Also¶
- File Operations - File I/O operations
- String Methods - String manipulation for input parsing
- Standard Library Reference - Complete stdlib reference
- Error Handling - Result and Maybe types