From OpenCog

The StateLink enables the creation of mutable state within the atomspace. It effectively creates a key-value pair, with the first atom being the key, and the second being the value. Of course, all Links can associate pairs of atoms; the StateLink differs from other link types in allowing only one value per key at any instant in time. Thus, adding a second StateLink (with an existing key) to the atomspace has the side-effect of automatically deleting the earlier StateLink (in a thread-safe, atomic fashion).

Thus, StateLinks resemble "variable = value" style assignments in procedural programming languages, where "variable" can only hold one value at any given time. In functional programming languages, such structures are sometimes called "boxes"; StateLinks are named boxes, with the "key" being the name of the box, and "value" being the contents of the box.

Unlike procedural or functional languages, there is no restriction that the "key" or "box name" be a fundamental type. It can be a compound object: i.e. it can be a Link as well as a Node. This allows StateLinks to be used to define "properties" on an Atom, thus resembling "class instances" in object-oriented programming, and so allowing "methods" and "members" to be declared on an atom.

Example: simple state

The following sets a "switch" to the "on" position:

    ConceptNode "switch"
    ConceptNode "on"

If the below is added to the atomspace:

    ConceptNode "switch"
    ConceptNode "off"

then the "switch" is turned "off"; the StateLink to the "on" position is automatically removed; the atomspace will contain only the link to the "off" position.

A working example is here: /examples/atomspace/state.scm

Example: object-oriented style

The first argument or "key" to the StateLink does not need to be a Node; it can be any Link. This allows a form of dynamic object-oriented-style structures to be defined in the AtomSpace. Thus, one can have one atom being a "class instance", a second atom being the "name" of a member (or "property") in that instance, and a third atom being the current "value".

For example, one can have a "class instance" named "foo", with a member (property) named "truthiness", currently having the numeric "value" of 0.76 by writing

    (ListLink (ConceptNode "foo") (PredicateNode "truthiness"))
    (NumberNode 0.76)

Using the ListLink in this way allows an arbitrary number of properties/members to be set on the "foo" atom.

A more detailed example is here: /examples/atomspace/property.scm

At this time, there is no particular optimizations in the C++ code to make the dereferencing of state any faster than other kinds of atomspace operations. In particular, there is no optimized or easy way of calling a "method" defined using the above construct.

Related ideas

Immutable state can be declared using DefineLink. The DefineLink can be used only once to declare an association; redefinitions will cause an error to be thrown. That is, to change a definition, the original DefineLink must first be manually deleted. Thus, redefinitions are not atomic, and so not thread-safe.

The DeleteLink implements a related idea, except that it allows exactly zero "definitions". Any attempt to ground a DeleteLink with a specific, closed-term value will cause that value to be removed from the atomspace.


To be precise, the StateLink only allows a single closed value per key; any number of open values are allowed. A "closed term" is an atom that has no free variables in it; an open term does contain free variables. The reason for this distinction is that it is useful to write StateLinks with VariableNodes in them, so that they can be used in GetLinks and PutLinks to find search, query, find and alter state.

By contrast, the DefineLink allows only one pairing, open or closed.

It's also useful to contrast to the DeleteLink, which allows exactly zero closed terms, but any number of open terms.

StateLink inherits from FreeLink, so that the distinction between open and closed terms is made by using the FreeLink implementation.

StateLink (just link DefineLink) inherits from UniqueLink, which provides the actual mechanics implementing uniqueness.