Data and the Outside World

All of this is built in; no imports: is needed. lp9 build links only the libraries inference found a use for.

The names and answers follow Lambda Prelude. Where they differ, it is mostly that reading what somebody else wrote answers a Maybe instead of stopping the program.

Files and Processes

File read:, File write:contents:, File append:contents:, File listDir: and the rest. A path that cannot be read or written stops the program.

File open: answers a file held open for reading and writing (a FileHandle), with what an append-only log needs:

Child processes are OS exec: (runs to the end and answers the exit code, standard output and standard error), OS spawn: (answers the pid at once), OS running: and OS kill:. On Windows the children get no console window.

Databases

SQLite is built in. For PostgreSQL and for MariaDB and MySQL, LP-9 speaks each protocol itself, so nothing is put beside the executable. All three answer the same selectors.

db := DB open: 'orders.db'.
db exec: 'INSERT INTO orders (name, due, price) VALUES (:name, :due, :price)'
   with: { name: 'stainless bar', due: (Date y: 2026 m: 10 d: 28), price: 1840.00s }.

rows := db query: 'SELECT name, price FROM orders WHERE due <= :d' with: { d: Date today }.
rows do: [ :r | ((r at: 'name') orElse: '(null)') displayNl ].

Parameters are named. :name becomes the connection's own placeholder (? on SQLite, $1 on PostgreSQL) and binds its value with its own type. A name the statement uses that is not given, and one given that it does not use, are both errors, so a misspelt key is found rather than bound as NULL.

A row's columns are Maybe[Str], and SQL NULL reads as absent.

withTx: commits if the block answers, rolls back if it fails, and lets the failure travel on. It works on SQLite and PostgreSQL alike.

PostgreSQL authenticates with SCRAM-SHA-256, and sslmode=require verifies the certificate. MariaDB takes mysql_native_password and MySQL 8's caching_sha2_password.

Two-Way SQL

A statement whose directives are SQL comments, so it runs as it is in a database tool, and render: turns it into the statement and its parameters. The language is Doma's, ported from Lambda Prelude's TORM.

Object subclass: #Find fields: (ids, active).

sql := SqlTemplate parse: 'SELECT id FROM users WHERE id IN /*ids*/(1, 2)
/*%if active */ AND active = 1 /*%end*/'.

r := sql render: (Find fields: { ids: #[ 3, 4, 5 ], active: true }) dialect: 'postgres'.
r text displayNl.        "... IN ($1, $2, $3) AND active = 1"

(sql render: (Find fields: { ids: #[ 9 ], active: false }) dialect: 'sqlite') text displayNl.
                         "... IN (?)"

A WHERE whose conditions all fall away goes with its keyword. dao: makes methods from a directory of SQL files, and entity: ties a table to a class. Both are expanded as the file loads, so a template that does not parse stops the program before it runs.

Network

TCP connect:port:, TCP listen:, TLS wrapClient:host:, Http get:, Http post:body:contentType:.

JSON and MessagePack

Json parse: answers a Maybe[Json], so text that is not JSON does not stop the program. A Json is one node of the document, and a leaf is read with the method for the type the program expects.

(Json parse: '{"name": "Alice", "total": 1234.50}') ifPresent: [ :o |
    (o at: 'name') stringValue displayNl.
    (o at: 'total') asDecimal displayNl ].       "1234.50"

The type of what is read is written where it is read, so everything computed from it is checked. A number with a point reads with asDecimal as an exact amount, and keeps its digits through a file and back; a Decimal is written as a string.

MsgPack parse: and MsgPack serialize: handle the same documents in MessagePack.

Tools for Text

The Clipboard and Images

Clipboard text and Clipboard text: s. Clipboard image reads the PNG a program put there, or else the bitmap of a screenshot.

Image decode: reads a PNG and answers Maybe[Image]; png writes one. Paint image:x:y:w:h: stretches a picture to a rectangle, and a copy at another size is made once and kept. A picture is an immutable value, so a description holding the same picture is the same piece and an unchanged region is not drawn again.

Dates and Times

Date, DateTime, Instant and TimeZone are in Design. To a database and to JSON, a Date goes as 2026-10-09 and an Instant as RFC 3339 in UTC with three fraction digits always, so the texts sort as the moments do.