Standard Library Overview
The Nic standard library provides essential functionality for systems programming: memory management, string handling, collections, I/O, threading, and more.
Installation
The standard library is installed to ~/.nicc/ when you run:
bash
make installFor development, you can use the local std/ directory:
bash
NIC_STD_PATH=. cabal run nicc -- run myfile.nicImport Conventions
Prelude (Auto-imported)
The prelude is automatically imported into every Nic program. It provides core types:
nic
// These are available without explicit import:
let maybe: Option[i32] = Some(42);
let result: Result[i32, string] = Ok(10);
let s = String::from("hello");
let v = Vec::empty[i32]();Standard Modules
Standard library modules use the std. prefix:
nic
import std.io; // File I/O
import std.mem; // Memory allocation
import std.args; // Command-line arguments
import std.parse; // String parsing
import std.async.thread; // Threading
import std.async.mutex; // Synchronization
import std.flags; // CLI flag parsingSelective Imports
Import specific items to avoid namespace pollution:
nic
import std.io(File, FileMode, open, close);
import std.mem(alloc, dealloc);
import std.parse(parse_i32, parse_bool);Glob Imports
Import everything from a module:
nic
import std.flags(*);Module Overview
| Module | Description |
|---|---|
| Prelude | Core types: Option, Result, String, Vec, StringMap, IntMap |
| std.mem | Memory allocation and manipulation |
| std.args | Command-line argument handling |
| std.parse | String parsing utilities |
| std.io | File I/O operations |
| std.async | Threading and synchronization |
| std.flags | CLI flag parsing with subcommands |
Design Principles
Explicit Resource Management
Nic avoids garbage collection. Resources are managed explicitly:
nic
let file = open("data.txt", FileMode::Read);
defer close(file); // Cleanup when scope exits
// Use the file...Error Handling with Result
Fallible operations return Result[T, E]:
nic
import std.parse(parse_i32);
fn read_number(s: string) -> Result[i32, string] {
return parse_i32(s);
}
match read_number("42") {
Ok(n) => println("Got: " + int_to_string(n)),
Err(e) => println("Error: " + e),
}Optional Values with Option
Values that may be absent use Option[T]:
nic
fn find_user(id: i64) -> Option[User] {
// Returns Some(user) or None
}
match find_user(123) {
Some(user) => println("Found: " + user.name),
None => println("User not found"),
}Generic Collections
Collections are generic and type-safe:
nic
let numbers = Vec::empty[i32]();
numbers.push(1);
numbers.push(2);
numbers.push(3);
let map = StringMap::empty[bool]();
map.insert("enabled", true);Directory Structure
~/.nicc/
├── prelude.nic # Auto-imported core types
└── std/
├── io/ # File I/O module
│ ├── mod.nic
│ └── file.nic
├── async/ # Threading module
│ ├── mod.nic
│ ├── thread.nic
│ └── mutex.nic
├── flags/ # CLI parsing module
│ ├── mod.nic
│ ├── types.nic
│ ├── parser.nic
│ ├── result.nic
│ └── help.nic
├── mem.nic # Memory module
├── args.nic # Arguments module
└── parse.nic # Parsing module