Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Attributes

Attributes are special runtime settings that modify block behavior, such as how many times a block repeats or how it selects which element to run.

Attributes are set by calling the standard library's attribute functions or by using the attribute keywords and are stored in the program's attribute stack. Each frame of the attribute stack stores a full set of attributes.

When a block resolves, it consumes attributes from the topmost attribute frame and replaces them with their default values.

Frames can be added to and removed from the attribute stack using [push-attrs] and [pop-attrs].

Working with attributes

Stable 4.0 exposes the attribute system in three complementary ways:

  • standard library helpers such as [rep], [sep], [sel], [mut], and [match]
  • plain keyword reads such as @rep and @step
  • angle-bracket accessors such as <@rep = 3> and <@sel>

The mutable attribute keywords also support immediate-block sugar:

@rep 3: {x}
xxx

The mutable forms are @rep, @sep, @sel, and @mut. The block-state keywords @step and @total are read-only.

Repetitions

By setting the repetitions attribute, you can control how many times the next encountered block will run. This attribute is set with the [rep] function or with @rep.

Example

[rep:10]{[step]\n}
# Output:
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10

Separator

The separator attribute controls what is printed between each block repetition. It is set using the [sep] function or @sep.

Example

[rep:4][sep:" and "]
It just keeps {going}...

# Output:
# It just keeps going and going and going and going...

The @sep keyword can also be read and written through accessor syntax:

<@sep = ",">[rep:3][sep:<@sep>]{x}
x,x,x

Selectors

The selector attribute controls how Ranty chooses which branch of a block to take. It does this using a special state machine object, which must be created separately but can be shared between blocks to coordinate their behavior. You can set it with [sel], [match], @sel, or <@sel = ...>.

Selector modes

ModeDescription
randomSelect a random element each time. (default)
oneSelect the same, random element each time.
forwardSelect in a wrapping sequence from first to last.
forward-clampSelect from first to last, then repeat the last element forever.
forward-mirrorSelect from first to last, then last to first, then start over.
reverseSelect in a wrapping reverse sequence from last to first.
reverse-clampSelect from last to first, then repeat the first element forever.
reverse-mirrorSelect in a from last to first, then first to last, then start over.
deckSelect each element once in a random sequence, then reshuffles.
deck-loopSelect each element once in a wrapping random sequence, without reshuffling.
deck-clampSelect each element once in a random sequence, repeating the final element.
deck-mirrorSelect each element once in a random sequence, then repeats the sequence backwards before reshuffling.
pingSelect from first to last, switching directions when a boundary element is reached.
pongSelect from last to first, switching directions when a boundary element is reached.
no-doubleSelect a random element each time, ensuring the same element never occurs twice in a row.
matchSelect from elements whose @on trigger equals the selector's stored value; otherwise, use untagged fallback elements. Cursor operations are unsupported.

Example

# Print every element of the block in a random order with no duplicates

<$s=[mksel:deck]>  # Create a "deck" selector
[sel:<s>]          # Apply the selector
[rep:all]          # Set repetitions
[sep:,\s]          # Set separator
{A|B|C|D|E|F|G|H}

# Output
# F, C, E, G, B, H, D, A

Match selection

Match selectors choose from elements tagged with @on.

[match: foo]{yes @on foo|no @on bar|fallback}
yes

If no tagged element matches, all untagged elements become the fallback pool. If there are no matching tagged elements and no untagged elements, the block raises a runtime selector error. When the block is weighted, weights are applied inside the chosen pool.

Mutator

The mutator attribute allows the user to supply a function (known as the "mutator function") that is called in place of each iteration of the block. The mutator function accepts the current block element as a callback parameter, which it can then call to produce output for that iteration.

This is extremely useful for applying filters or post-processing to a block at a per-iteration level.

[rep: all]
[sep: \n]
[mut: [?:elem] { [elem]! }] # Just adds an exclamation point
[mksel: forward |> sel]
{
    One | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
}

You can also choose how many times you want to run the element, or even not run it at all.

# Without mutator
[rep: all]
[sep: \s]
[sel: forward]
{ the | quick | brown | fox }
# -> the quick brown fox


# With mutator
[mut: [?: el] { [el] [el |> rev] }]
[rep: all]
[sep: \s]
[sel: forward]
{ the | quick | brown | fox }
# -> theeht quickkciuq brownnworb foxxof

The @mut keyword supports the same attribute state:

@mut [?: elem] { [elem]! }: {foo}
foo!

Block state

@step and @total expose the currently active block's iteration state.

  • @step is the current zero-based iteration index.
  • @total is the current total iteration count, or <> for infinite repeaters.

These keywords are read-only. They report 0 when no repeater is active.