Dynamic Environment

Atomo has a dynamic system similar to Scheme's parameterize and Common Lisp's defvar.

The usual convention of using *earmuffs* for dynamic variable names is fine, but it's not really necessary as it's harder for them to collide with normal variables (accessing is either explicit or lexical, and updating is explicit).

top define: name as: root  root

Creates a new dynamic variable called name, defining an accessor in top. The accessor simply performs name _?.

If the dynamic variable already exists, it is replaced.

Example:

> define: *foo* as: 10
10
> *foo* _?
10
> *foo*
10
name _?  any

Retrieves the binding for name from the dynamic environment.

Example:

> define: *foo* as: 10
10
> *foo* _?
10

Normally you won't need to do this, since define:as: defines an accessor for you, so you can just say the name.

name =! value  value

Updates the most recent binding for name as value. This cannot replace the root value.

Example:

> define: *foo* as: 0
0
> with: *foo* as: 1 do: { *foo* =! 2; *foo* }
2
> *foo* =! 2
ERROR: <error @(unbound-dynamic: "*foo*")>
with: name as: binding do: action  any
  | action is-a?: Block

Calls action with name bound as binding.

Example:

> define: *foo* as: 0
0
> with: *foo* as: 1 do: { *foo* }
1
> *foo*
0
with: bindings do: action  any
  | bindings is-a?: List
  | action is-a?: Block

Calls action with the given Associations of variables to their new bindings. Expands into multiple with:as:do: calls.

Calls action with name bound as binding.

Example:

> define: *foo* as: 0
0
> define: *bar* as: $a
$a
> with: [*foo* -> 1, *bar* -> $b] do: { [*foo*, *bar*] }
[1, $b]
> [*foo*, *bar*]
[0, $a]
modify: name as: modifier do: action  any
  | action is-a?: Block
  | modifier responds-to?: @call:

Similar to with:as:do:, but passes the current value to modifier to yield the new binding.

Example:

> define: *foo* as: 0
0
> modify: *foo* as: @(+ 1) do: { *foo* }
1
> *foo*
0