Concept guide
Safe by design: danger, failure, and memory
Vision puts risky work in the source where you can see it. World touches carry a marker, failures stay beside the operation, and returned data has a clear owner. Concurrency and C interop keep their boundaries visible too.
Mark contact with the world
Vision checks >> in both directions. File access, networking, clocks, randomness, and other tracked world touches need the marker. A calm operation rejects it. The rule follows calls as well, so a verb that reaches the world through another verb must carry >> on its declaration and call sites.
!! is narrower. It marks a step that cannot be undone, such as removing a file, renaming over one, stopping a process, or sending a signal. Recoverable world touches reject !!, which keeps the mark useful instead of letting it become decoration.
>> to begin:
>> !! remove the file at "scratch.txt"
| missing: stop
| unwritable: stop>> to begin:
>> !! remove the file at "scratch.txt"
| missing: stop
| unwritable: stopHow Vision thinks introduces the world-touch boundary from the calm side. This page follows it into the places where work can fail or cross a runtime boundary.
Keep failure beside the work
Checked Vision operations cannot quietly drop a failure. The file read below covers missing and unreadable; converting the bytes to text separately covers badtext. Each clause says what the program should do before execution can continue.
>> to begin:
>> read the file at "poem.txt" returning the poem
| missing: say "no poem yet" and stop
| unreadable: say "the poem cannot be read" and stop
the poem decoded as text returning the readable
| badtext: say "the poem is not valid text" and stop
say the readable>> to begin:
>> read the file at "poem.txt" returning the poem
| missing: say "no poem yet" and stop
| unreadable: say "the poem cannot be read" and stop
the poem decoded as text returning the readable
| badtext: say "the poem is not valid text" and stop
say the readableThis guide uses stop for the shortest path. A deeper caller can also receive a failure handed on by a helper verb. The Effects and failure reference will cover every failure tag and resolution form.
Keep secrets distinct from text
A field declared secret is not ordinary text. Vision keeps that type through assignments and blocks direct output of the protected value. Reveal and wipe are deliberate operations, so code does not leak a passphrase through an everyday say by accident.
kind strongbox:
passphrase is a secret
to begin:
the box is a strongbox
box.passphrase is "hunter2"
say "the box is sealed"kind strongbox:
passphrase is a secret
to begin:
the box is a strongbox
box.passphrase is "hunter2"
say "the box is sealed"Return values to a clear owner
Most Vision code says nothing about memory. The compiler records heap-owning values, frees local data when its scope ends, and cleans up caller-owned return values when they are ignored, replaced, or leave the caller's scope. There is no garbage collector in that path.
The compiler treats a heap-owning result as belonging to its caller. If a verb returns an owner it already made, ownership transfers. If it returns borrowed data—a text parameter, a field, or an item read from a list—the compiler clones that value at the return boundary. The caller receives an independent owner either way.
to echo(source: text), returns text:
answer source
to begin:
the original is "caller-owned"
the returned is echo(original)
say "original: {the original}"
say "returned: {the returned}"to echo(source: text), returns text:
answer source
to begin:
the original is "caller-owned"
the returned is echo(original)
say "original: {the original}"
say "returned: {the returned}"An unusual escape can still outlive the region that made it, such as an owned value stored into a longer-lived field. When the compiler cannot prove that lifetime, it requires a visible memory: block; it does not guess or switch to hidden reference counting. The precise escape rules belong in the Host and C interop reference.
Join concurrent work before moving on
all at once: opens a bounded concurrent region. Each ask a strand called block runs in its own worker, and the closing edge is a join: code after the block does not run until every strand has finished. In the current compiler, the block carries >> and is classified as a world touch.
A channel carries typed values between those workers. It closes automatically after its last sending strand exits, and for each item received from drains the remaining values before ending. There is no manual close step. Sending and receiving are in-process operations and stay unmarked; the visible >> belongs to the enclosing all at once: region.
>> to begin:
the work is a channel of whole number, with room for 2
>> all at once:
ask a strand called producer:
send 2 to the work
send 5 to the work
send 7 to the work
ask a strand called consumer, returning the total:
the tally is 0
for each item received from the work:
the tally is the tally plus the item
answer the tally
say "joined total: {the total}">> to begin:
the work is a channel of whole number, with room for 2
>> all at once:
ask a strand called producer:
send 2 to the work
send 5 to the work
send 7 to the work
ask a strand called consumer, returning the total:
the tally is 0
for each item received from the work:
the tally is the tally plus the item
answer the tally
say "joined total: {the total}"Strand bodies are isolated. They may use values created inside the strand and channels captured from the outer scope, but they cannot read other outer local values. A result-bearing strand must answer on every path, and its result must be a whole, decimal, yes-or-no, byte, or text. Nested concurrency inside a strand is not supported in the current surface. Those constraints keep worker state explicit.
Know which boundary you are crossing
by hand: is the direct escape hatch. Its indented body is raw C, preserved as a sealed section and emitted into the surrounding C function. Vision does not infer the C code's effects, failures, or lifetime behavior. Once a program enters that section, those checks are the author's responsibility.
to read host counter:
the counter is 0
by hand:
counter = 42;
answer counter
to begin:
say "host counter: {read host counter}"to read host counter:
the counter is 0
by hand:
counter = 42;
answer counter
to begin:
say "host counter: {read host counter}"The other boundary forms do different jobs. this program understands zlib asks the compiler to inspect an installed C library's declarations, then emits the header and build link directive for that library. this program exposes greet to the host marks a Vision verb for the generated C ABI in library mode. A host that receives heap-owned text from an exposed verb owns that result and must release it.
this program links (settings) does not bind C at all. It brings declarations from a peer settings.vis file into the program. this program links (settings as config) keeps them under a config. namespace. The Host and C interop reference will cover supported ABI shapes, library discovery, and linked-file name rules without turning this guide into an edge-case table.
Try one safe change and one unsafe one
In the concurrency example, send one more number and predict the new total before running it. Then try to read an outer local value from the producer strand. The compiler rejects the second change because that local is not captured into the worker.
Finally, change echo so it returns a new interpolation instead of its parameter. The output stays the same, but the ownership path changes: the new text transfers directly instead of being cloned from a borrow. The next concept guide, Generics and monomorphization, will show how Vision specializes reusable verbs without giving up these checks.