at:tutorial:appendix
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
at:tutorial:appendix [2008/07/10 14:31] – * tvcutsem | at:tutorial:appendix [2008/07/10 16:08] – * tvcutsem | ||
---|---|---|---|
Line 102: | Line 102: | ||
==== Vector ==== | ==== Vector ==== | ||
- | A vector is a dynamically resizable AmbientTalk table (aka array). Vectors may be created as follows: | + | A vector is a dynamically resizable AmbientTalk table (aka array). Indexed reading from and writing to a vector is fast (O(1)). Adding elements to a vector is mostly fast, but sometimes requires a resize of the vector. Vectors support the traditional stack operations '' |
+ | |||
+ | Vectors may be created as follows: | ||
< | < | ||
Line 125: | Line 127: | ||
// write idx'th element or raise IndexOutOfBounds exception | // write idx'th element or raise IndexOutOfBounds exception | ||
- | //atPut(idx, val) | + | atPut(idx, val) |
// iterate over the vector | // iterate over the vector | ||
Line 148: | Line 150: | ||
select(start, | select(start, | ||
- | // appends an element to the back of the vector | + | // appends an element to the back of the vector. Returns |
- | // returns | + | |
add(element) | add(element) | ||
// alias for add(element) | // alias for add(element) | ||
Line 203: | Line 204: | ||
asTable() | asTable() | ||
</ | </ | ||
+ | |||
+ | The file '' | ||
==== List ==== | ==== List ==== | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | The list module defines two styles to manipulate cons-cells: an object-oriented and a functional style. The object-oriented style represents cons-cells as '' | ||
+ | |||
+ | The functional style allows one to manipulate lists by means of the following functions: | ||
+ | |||
+ | < | ||
+ | cons(car, | ||
+ | car(conscell) -> the car | ||
+ | cdr(conscell) -> the cdr | ||
+ | list(@items) -> a cons-cell representing the head of a list | ||
+ | </ | ||
+ | |||
+ | Lists (cons-cells or the empty list) support the following operations: | ||
+ | |||
+ | < | ||
+ | // accessors for car and cdr | ||
+ | car() | ||
+ | cdr() | ||
+ | |||
+ | // the length of the list | ||
+ | length() | ||
+ | |||
+ | // whether the list is empty or not | ||
+ | isEmpty() | ||
+ | |||
+ | // returns the nth element of the list | ||
+ | nth(n) | ||
+ | |||
+ | // apply a unary function to each element of the list | ||
+ | each: fun | ||
+ | |||
+ | // apply a function to each element and its index in the list | ||
+ | // i.e. list.eachWithIndex: | ||
+ | eachWithIndex: | ||
+ | |||
+ | // map a unary function over the list, returning a new list | ||
+ | map: fun | ||
+ | |||
+ | // accumulate a value over a list | ||
+ | inject: init into: accum | ||
+ | |||
+ | // return a new list whose elements satisfy the unary predicate | ||
+ | filter: cond | ||
+ | |||
+ | // does the list contain the element? | ||
+ | contains(elt, | ||
+ | |||
+ | // implode or join a list of text strings | ||
+ | implode() | ||
+ | join(txt) | ||
+ | |||
+ | // drop the first n elements from the list | ||
+ | tail(n) | ||
+ | |||
+ | // prepend an element to the list | ||
+ | add(elt) | ||
+ | |||
+ | // insert an element in the list (functionally) | ||
+ | insert(atPos, | ||
+ | |||
+ | // return a new list where the element atPos is deleted | ||
+ | delete(atPos) | ||
+ | |||
+ | // functional append | ||
+ | append(aList) | ||
+ | |||
+ | // return the index of the first matching element, or nil if none is found | ||
+ | find: filter | ||
+ | |||
+ | // return the index in the list of the element or nil of not found | ||
+ | indexOf(elt, | ||
+ | |||
+ | // return a list where the given element is removed | ||
+ | remove(elt, cmp := DEFAULTCOMPARATOR) | ||
+ | |||
+ | // return a new list where all objects for which filter(elt) is true are removed | ||
+ | removeAll: filter | ||
+ | |||
+ | // convert the list into a table | ||
+ | asTable() | ||
+ | </ | ||
+ | |||
+ | The file '' | ||
+ | |||
+ | |||
+ | ===== Top-level functions ===== | ||
+ | |||
+ | The file '' | ||
+ | |||
+ | ==== Asynchronous control structures ==== | ||
+ | |||
+ | The '' | ||
+ | |||
+ | '' | ||
+ | < | ||
+ | loop: { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | An '' | ||
+ | < | ||
+ | whenTrue: booleanFuture then: { ... } else: { ... } | ||
+ | </ | ||
+ | |||
+ | Asynchronous while loop over future-type conditional: | ||
+ | < | ||
+ | asLongAs: { /* asynchronous computation returning a future */ } do: { ... } | ||
+ | </ | ||
+ | |||
+ | ==== Mobile code ==== | ||
+ | |||
+ | The function '' | ||
+ | |||
+ | < | ||
+ | def mobileAdder(x) { | ||
+ | script: { |n| x + n } carrying: [`x] | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | A call to '' | ||
+ | |||
+ | The constructor function '' | ||
+ | |||
+ | < | ||
+ | def foo := 42; | ||
+ | def i := isolate: { | ||
+ | ... | ||
+ | } passAs: { |foo| | ||
+ | / | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The above code defines an isolate object '' | ||
+ | |||
+ | ===== Custom Exceptions ===== | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | < | ||
+ | deftype FooException; | ||
+ | </ | ||
+ | |||
+ | Next, define a prototype exception object using the '' | ||
+ | |||
+ | < | ||
+ | def XFooException := createException(FooException); | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | |||
+ | < | ||
+ | raise: XFooException.new(" | ||
+ | </ | ||
+ | |||
+ | If your custom exception requires additional state, you can define it as an extension of the prototype exception. If you define a custom constructor, | ||
+ | |||
+ | < | ||
+ | deftype IndexOutOfBounds; | ||
+ | def XIndexOutOfBounds := createException(IndexOutOfBounds) with: { | ||
+ | def min; | ||
+ | def max; | ||
+ | def idx; | ||
+ | def init(min, max, idx) { | ||
+ | super^init(" | ||
+ | self.min := min; | ||
+ | self.max := max; | ||
+ | self.idx := idx; | ||
+ | }; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The exception module also exports an auxiliary function '' | ||
+ | |||
+ | ===== Language Extensions ===== | ||
+ | |||
+ | The files in the '' | ||
+ | |||
+ | ==== Futures and Multifutures ==== | ||
+ | |||
+ | === Futures === | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | The module exports the type tags '' | ||
+ | * Tagging an asynchronous message with '' | ||
+ | * Tagging a message with '' | ||
+ | * Tagging a message with '' | ||
+ | |||
+ | Messages can be automatically associated with a future by invoking the '' | ||
+ | |||
+ | The futures module also exports the function '' | ||
+ | |||
+ | Futures can also be created and resolved manually: | ||
+ | < | ||
+ | import / | ||
+ | def [fut, res] := makeFuture(); | ||
+ | when: someAsynchronousComputation() becomes: { |value| | ||
+ | res.resolve(value); | ||
+ | } | ||
+ | fut // return the future to a client | ||
+ | </ | ||
+ | |||
+ | Finally, the futures module also provides some auxiliary functions, of which '' | ||
+ | |||
+ | < | ||
+ | when: (group: [ a<-m(), b<-n() ]) becomes: { |values| | ||
+ | def [aResult, bResult] := values; | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Multifutures === | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | A multifuture is constructed as follows: | ||
+ | < | ||
+ | def [mf, resolver] := makeMultiFuture(n, | ||
+ | </ | ||
+ | |||
+ | The parameter '' | ||
+ | |||
+ | A multifuture accepts the following listeners: | ||
+ | |||
+ | < | ||
+ | whenEach: multiFuture becomes: { |val| ... } | ||
+ | </ | ||
+ | |||
+ | This listener is invoked whenever the future is resolved with a new value. Its code can thus be executed multiple times. | ||
+ | |||
+ | < | ||
+ | whenAll: multiFuture resolved: { |values| | ||
+ | ... | ||
+ | } ruined: { |exceptions| ... } | ||
+ | </ | ||
+ | |||
+ | This listener invoked if all results have been gathered (only possible if the maximum number of results is known). If there are no exceptions, only the first code block is triggered. If there are only exceptions, the first block is still invoked with an empty value table. | ||
+ | |||
+ | Note the following properties of multifutures: | ||
+ | * It is allowed to register a whenAll: | ||
+ | * As with futures, it is legal to send asynchronous messages to the multifuture, | ||
+ | * When a multifuture A is resolved with a multifuture B, all of B's eventual values/ | ||
+ | * A whenEach: | ||
+ | * Like with futures, multifutures can be explicitly created, e.g.: | ||
+ | < | ||
+ | * Multifutures can be attached to messages by annotating an asynchronous message with the @Gather(n) type tag. | ||
+ | * Adding a when: | ||
+ | |||
+ | The multifutures module also exports an abstraction known as a " | ||
+ | |||
+ | When the message sent to a multireference is annotated with @Due(t), the timeout is applied to the implicit multifuture, | ||
+ | |||
+ | ==== Dynamic Variables ==== | ||
+ | |||
+ | ==== Ambient References ==== | ||
+ | |||
+ | ==== Structural Types ==== | ||
+ | |||
+ | ==== Traits ==== |
at/tutorial/appendix.txt · Last modified: 2021/09/24 10:28 by elisag