Console
Write text to the console. Console gives you Console.Line, which appends a line to the
console output channel — a reactive sink the console
driver drains and prints on each cycle. Because the
call runs inside the reactive program, a line written from a value that later changes is simply written
again on the next cycle.
Contents
Functions
Functions
Console.Background
Sets the background colour for a block.
Parameters
| Name | Type | Description |
|---|---|---|
colour | Colour.RGBA | The colour to fill behind text and lines. Its alpha channel lets the existing background show through. |
Holes
| Name | Returns | Description |
|---|---|---|
content | nothing | The text and lines to write on the chosen background. |
Returns
Returns nothing — every piece of text or line written in the content is drawn on the given background colour.
Example
Console.Background Colour.RGBA.Red
Console.Line "Build failed"Console.Foreground
Sets the text colour for a block.
Parameters
| Name | Type | Description |
|---|---|---|
colour | Colour.RGB | The colour to draw text and lines in. |
Holes
| Name | Returns | Description |
|---|---|---|
content | nothing | The text and lines to write in the chosen colour. |
Returns
Returns nothing — every piece of text or line written in the content is drawn in the given foreground colour.
Example
Console.Foreground Colour.RGB.Green
Console.Line "All tests passed"Console.Line
Writes a line of text to the console output.
Parameters
| Name | Type | Description |
|---|---|---|
text | Text | The line to write. |
Returns
Returns nothing — the line is appended to the console output channel.
Example
Console.Line "Hello, world"Console.Prefix
Prefixes every line written in a block.
Holes
| Name | Returns | Description |
|---|---|---|
prefix | nothing | Run at the start of every new line to write the prefix. Its output — text and colours — is emitted before the line's own content. |
content | nothing | The lines to write. At the start of each new line the prefix hole runs first. |
Returns
Returns nothing — the content is written to the console output channel with the prefix applied to the start of each line.
Example
Console.Prefix
Console.Prefix.prefix
Console.Text "> "
Console.Prefix.content
Console.Line "first"
Console.Line "second"> first and > second, prefixing each line.Console.Text
Writes text without ending the line.
Parameters
| Name | Type | Description |
|---|---|---|
text | Text | The text to write. |
Returns
Returns nothing — the text is appended to the current line of the console output channel, with no trailing line break. When it is the first thing written on a new line, the active prefix is written before it.
Example
Console.Text "Loading"
Console.Text "..."Loading... on a single line, leaving the cursor at the end of it.Filling multiple holes at the call site
The open question above is now settled. At the call site each hole is named in full —
the function's name, then the hole's own — so the label cannot be mistaken for anything else. A
bare sample would be tempting, but something else already in scope might be called
sample too (a piece of state, say), and the two would be
ambiguous; the fully-qualified Scene.Field.sample can clash with nothing. (Its lowercase
final segment also keeps it distinct from a call, which is
capitalised.) So Console.Prefix's two holes are written in
full:
Console.Prefix
Console.Prefix.prefix
Console.Text "> "
Console.Prefix.content
Console.Line "first"
Console.Line "second"A single-hole call keeps a shorthand: with only one block to fill there is nothing to disambiguate,
so the label is dropped and the block goes straight into the call's indented content, as
Console.Foreground shows. This is worth keeping because
the single-hole call is the common case — most of the user interface is containers with
a single content block — and forcing a label there would roughly double the line count for no
gain. Names are needed only once a call offers more than one block.
Holes that take arguments
A hole's block can take arguments, and it binds them the way a function does — with
INPUT lines — returning its value as the
block's last expression. Picture a Scene.Material that wraps some geometry in a material:
its material hole is handed a point in space and returns the colour there, and its
object hole takes nothing and just places the geometry.
FUNCTION Scene.Material
HOLE Colour.RGB material
INPUT Maths.Vector3 coordinate
HOLE objectAt the call site each block is still opened by its hole name. material binds the
coordinate it is given and returns a colour; object takes no arguments:
Scene.Material
Scene.Material.material
INPUT Maths.Vector3 coordinate
LET Maths.Real height = Maths.Vector3.Y coordinate
Colour.RGB.Grey height
Scene.Material.object
Scene.Sphere 1.0A generic that threads through the holes
A hole's types can depend on a type parameter of the function, chosen by the caller. A
procedural Scene.Field is a fair motivating case: it is generic over the value it samples,
SampleType, declared in parentheses on the function. That one parameter then appears
inside the holes — as sample's return, and as the type of shade's
INPUT:
FUNCTION Scene.Field(SampleType)
HOLE SampleType sample
INPUT Maths.Vector3 coordinate
HOLE Colour.RGB shade
INPUT SampleType valueSampleType, shared across both holes.The caller supplies that type once, in parentheses on the call — exactly as any other generic call already does — and it flows into both blocks. Here it is a scalar field: Perlin noise sampled per point, shaded to grey.
Scene.Field(Maths.Real)
Scene.Field.sample
INPUT Maths.Vector3 coordinate
Maths.Noise.Perlin coordinate
Scene.Field.shade
INPUT Maths.Real value
Colour.RGB.Grey valueMaths.Real is given once and reused by Scene.Field.sample and Scene.Field.shade.Passing an existing function
A hole need not be filled with a fresh block. When an existing function already has the shape a hole
wants, it can be named directly — but the exact spelling is still open. Three forms are on the
table, each shown filling both of Scene.Field's holes
(Maths.Noise.Perlin maps a coordinate to a value, Colour.RGB.Grey a value to
a colour).
Label, then reference. The hole's qualified label and then the function, on one line. Explicit, but a label and a function sitting side by side read a little like two calls run together — which is what makes it feel slightly off:
Scene.Field(Maths.Real)
Scene.Field.sample Maths.Noise.Perlin
Scene.Field.shade Colour.RGB.GreyNamed argument. The hole's name, an =, then the function. A bare word
followed by = is a shape the language uses nowhere else, so the name needs no qualifying
to stay unambiguous — a state also called sample can't be
confused with it — and it reads like the assignment it is:
Scene.Field(Maths.Real)
sample = Maths.Noise.Perlin
shade = Colour.RGB.Grey= marks it, so a bare name is safe.The same name = carries a whole block just as easily. When the value is not a reference
but a fresh function, it follows the =, indented beneath — the return type is not
repeated, since the hole already fixes it, and no FUNCTION keyword is needed, because a
named argument whose value is a block can only be a hole:
Scene.Field(Maths.Real)
sample =
INPUT Maths.Vector3 coordinate
Maths.Noise.Perlin coordinate
shade =
INPUT Maths.Real value
Colour.RGB.Grey valueSo one form scales from a reference to a full block. It also generalises past holes: the same
name = value could name ordinary value arguments too, whenever a call reads more clearly
with them spelled out rather than left positional.
Colour.RGB.New
red = 0.2
green = 0.6
blue = 0.9Positional. Keep the holes positional, like every other argument, and either drop in
a reference or an inline anonymous FUNCTION.
No new syntax at all, but the reader has to count positions to see which hole is which:
Scene.Field(Maths.Real) Maths.Noise.Perlin Colour.RGB.GreyScene.Field(Maths.Real)
FUNCTION Maths.Real
INPUT Maths.Vector3 coordinate
Maths.Noise.Perlin coordinate
FUNCTION Colour.RGB
INPUT Maths.Real value
Colour.RGB.Grey valueFUNCTION keyword makes each block an explicit anonymous function.