Sen descrición

Herbert Vojčík c86fa13649 Axon docs. %!s(int64=6) %!d(string=hai) anos
src fc91e85ebd Extract Axon into Axxord-Axon category. %!s(int64=6) %!d(string=hai) anos
.gitignore 084a65a91b Initial commit. Extracted from Trapped. %!s(int64=9) %!d(string=hai) anos
Gruntfile.js ef91544d33 Shape into Axxord, step 2. %!s(int64=6) %!d(string=hai) anos
LICENSE-MIT 084a65a91b Initial commit. Extracted from Trapped. %!s(int64=9) %!d(string=hai) anos
README.md c86fa13649 Axon docs. %!s(int64=6) %!d(string=hai) anos
bower.json ef91544d33 Shape into Axxord, step 2. %!s(int64=6) %!d(string=hai) anos
deploy.js ef91544d33 Shape into Axxord, step 2. %!s(int64=6) %!d(string=hai) anos
devel.js e67e5b041d Move to amber 0.19.1. %!s(int64=6) %!d(string=hai) anos
index.html ef91544d33 Shape into Axxord, step 2. %!s(int64=6) %!d(string=hai) anos
local.amd.json ef91544d33 Shape into Axxord, step 2. %!s(int64=6) %!d(string=hai) anos
package.json ef91544d33 Shape into Axxord, step 2. %!s(int64=6) %!d(string=hai) anos
testing.js e227741785 Shape into Axxord, step 3. %!s(int64=6) %!d(string=hai) anos

README.md

Axxord

Small blackboard system for Amber Smalltalk.

Axon

Axon is a pub-sub system used in Axxord. It is fully generic, so it can be used for other purposes as well, without using the rest of the library.

It consists of two components: Axon abstract base class (and its implemenetation SimpleAxon), which are subscription managers; and AxonInterest abstract base class (and its pluggable implementation PluggableInterest) that represent the actual subscription.

You can create an axon, like in axon := SimpleAxon new. Then, you will add some interests in an aspect, as in axon addInterest: (PluggableInterest new accept: [:aspect | aspect = #amount] enact: [Transcript show: 'Amount is '; show: aThing amount; cr]). It is not prescribed what an aspect can be, or an aspect of what it is. It is used only to distinguish whether the change is related to the interest or not (as in previous example, one is interested in changes of #amount).

Whenever the change in some aspect happens for the object axon is watching, axon should be let known, using axon changed: #amount. You can also tell an axon that everything has changed, using axon changedAll. Axon then makes related interests enact, eventually (it may or may not happen immediately in the same thread, so enact should actually check if it is still interesting when it takes its turn).

There is no removeInterest:. The interest removes itself by signalling, as in PluggableInterest accept: [:aspect | aspect = #enabled] enact: [aThing isEnabled ifTrue: [Transcript show: 'still alive'; cr] ifFalse: [AxonOff signal]].

Axon and friends are all in their dedicated Axxord-Axon category / package.

Axes

Axes is hierarchical index used to access blackboard data.

Axes is an array of elements: either strings, numbers or a sub-arrays. These are used to denote the (relative) location of a piece of data in a hierarchical object, and is used to read or write from / to this position.

Elements of a path are equivalent to elements of paths in classic file systems: each elements is one step deeper in a tree hierarchy. Thus, to read a data denoted by a path, Axes starts from actual position, reads the contents denoted by first element, use the result to read the contents denoted by second elements etc. until the end. To write the data, the algorithm is similar to reading one, byt the last element is used to write the data instead.

  • if string path element is read from foo, foo at: aString is performed;
  • if string path element is written to foo, foo at: aString put: value is performed;
  • if number path element is read from foo, foo at: aNumber is performed;
  • if number path element is written to foo, foo at: aNumber put: value is performed;
  • if subarray path element #(bar) is read from foo, foo bar is performed;
  • if subarray path element #(bar) is written to foo, foo bar: value is performed.

###API


Object >> atAxes: aCollection ifAbsent: aBlock

For example container atAxes: #((todos) 1 done) ifAbsent: [...]' essentially does

| x |
x := container todos at: 1.
^ x at: 'done'

But, whenever:

  • container fails to perform todos, or
  • container todos fails to perform at:ifAbsent:, or
  • container todos does not contain index 1, or
  • container todos at: 1 fails to perform at:ifAbsent:, or
  • container todos at: 1 does not contain index 'done',

the ifAbsent block value is returned.


Object >> atAxes: aCollection ifAbsent: aBlock put: anObject

For example container atAxes: #((todos) 1 done) ifAbsent: [...] put: 'foo' essentially does

| x |
x := container todos at: 1.
^ x at: 'done' put: 'foo'

But, whenever:

  • container fails to perform todos, or
  • container todos fails to perform at:ifAbsent:, or
  • container todos does not contain index 1, or
  • container todos at: 1 fails to do at:put:,

the ifAbsent block value is returned.


Axes class >> parse: aString

Parses a string to get a proper array index to use with atAxes: API.

The syntax is resembling Smalltalk literal array syntax very closely. For example Axes parse: '(value)' and Axes parse: '(todos) 1 done' produce #((value)) and #((todos) 1 done) as results.

Syntactic sugar: as (foo) happens often, to denote unary selector, it can be written equivalently as ~foo, to improve readability. So above Axes' parseable string representation would likely be written '~value' and '~todos 1 done' instead.