You tell dt what to do by giving it commands.
If you want to know what commands are defined, you can use the
which will produce a quote of all defined command names. You can
see what a command does by using the
To see all defined commands and their usage at the same time, you can use the
❯ dt help quit % ( <a> <b> -- <c> ) Modulo two numeric values. In standard notation: a % b = c * ( <a> <b> -- <c> ) Multiply two numeric values. + ( <a> <b> -- <c> ) Add two numeric values. - ( <a> <b> -- <c> ) Subtract two numeric values. In standard notation: a - b = c ... ( <original> -- ? ) Unpack a quote. <etc>
The above is truncated, but the format here is:
The command name, for example
The "stack effect" on dt's state, for example
( <a> <b> -- <c> )which indicates it will take as input the two most-recent values as input (
<b>) and produce one new value (
<c>). The syntax for effects may be refined over time. A
?in a stack effects indicates an unknowable effect, it could be 0, 1, or many values.
A description that tries to be helpful. It's doing its best!
Everything can be considered a command. Semantically, everything that dt code defines is a command regardless of how it may be implemented. If you write
5it's a command to dt to produce an integer value of 5. If you write
[it's a command to dt to begin a quote and
]is a command to end a quote.
This isn't just theory mumbo-jumbo, it's practical. Everything in dt is always strictly evaluated left to right. There is no forward parsing, no function lifting, and there is no fancy grammar with lookaheads. Given enough time, it's always possible to analyze a dt program and understand (IO aside) exactly what the state should be based on the code that precedes it.
Quoted code is parsed as-is. Booleans, numbers, and Strings are parsed normally and any commands in a quote are not immediately executed.
There are two forms of delayed execution:
A deferred command, which is a
\character prefixed on a command name.
A quote, which is an opening bracket
[and a closing bracket
]with any number of values and commands in between.
The most common use of both of these forms is in defining new commands:
» [ "Hello world!" pl ] \greet def » greet Hello world!
Here we have quoted
"Hello world!" pl which does not immediately execute, and
the deferred the command
greet. We use it like you'd use a "symbol" in other
def to define it as a new command.
def takes an action and a name, and defines a command that can be used for the
rest of the calling scope. If the action is a deferred command, using the new
command in the future will execute the deferred command. If the action is a
value like a boolean, number, or string, using the command will produce that
If you'd like to define a command and its usage as well, use the longer
define command like so:
» [ "Hello world!" pl ] » "( -- ) Greet the whole world." » \greet define » greet Hello world! » \greet usage pl ( -- ) Greet the whole world.
If you'd like to bind one or more values to a command name, without executing
them when the command name is used, use the
» 1 \a: » a pl 1 » \pl [b]: » b pl \pl » # Unlike def, : also works for multiple terms. It binds left-to-right » 3  "five" [c d e]: » c pl 3 » d pl [ 4 ] » e pl five
To immediately execute a deferred command or a quote, use
» [ "Hi friend." pl ] do Hi friend.
To copy one command to another, use
alias. This also copies the usage
» \pls \PLZ alias » [ "Hello" "my "friend" ] PLZ Hello my friend
This can be used in other scopes to keep the prior definition around but redefine the canonical definition.
: bindings are scoped to the calling context and sub-contexts.
This means you can have local definitions that don't escape or redefine things they don't intend to.
» [ "Hi friend." \greeting: greeting pl ] do Hi friend. » greeting warning(dt.handleCmd): Undefined: greeting
This also means you can locally "shadow" a definition that already exists and not worry about that definition leaking out.
» 5 \n: » [ "N" \n: n pl ] do N » n pl 5