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 15:29] – Added tvcutsem | at:tutorial:appendix [2008/07/10 17:21] – added tvcutsem | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Appendix ====== | + | ====== Appendix: Libraries |
In the appendix, we explain useful libraries available to the AmbientTalk/ | In the appendix, we explain useful libraries available to the AmbientTalk/ | ||
Line 383: | Line 383: | ||
The exception module also exports an auxiliary function '' | 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| ... } | ||
+ | </ | ||
+ | |||
+ | The above 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| ... } | ||
+ | </ | ||
+ | |||
+ | The above listener is invoked if all results have been gathered (only possible if the maximum number of results is known) or when the '' | ||
+ | |||
+ | 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 ==== | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | A dynamic variable can be defined as follows: | ||
+ | < | ||
+ | def name := dynamicVariable: | ||
+ | </ | ||
+ | |||
+ | It can be read as follows: | ||
+ | < | ||
+ | ?name or name.value | ||
+ | </ | ||
+ | |||
+ | It can be assigned only within a limited dynamic scope, as follows: | ||
+ | < | ||
+ | with: name is: newval do: { code } | ||
+ | // or | ||
+ | name.is: newval in: { code } | ||
+ | </ | ||
+ | |||
+ | When '' | ||
+ | |||
+ | By convention, we prefix the names of dynamic variables with a '' | ||
+ | |||
+ | You can find more usage examples of dynamic variables in the unit test included in the file '' | ||
+ | |||
+ | ==== Ambient References ==== | ||
+ | |||
+ | Ambient references are defined in the module ''/ | ||
+ | |||
+ | < | ||
+ | import / | ||
+ | deftype Printer; | ||
+ | def printers := ambient: Printer; | ||
+ | </ | ||
+ | |||
+ | In the above code, '' | ||
+ | |||
+ | Ambient references ship with two so-called " | ||
+ | |||
+ | ==== Structural Types ==== | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | A structural type can be branded with type tags. In this case, objects only conform to the type if they are structurally conformant **and** if they are tagged with the structural type's brands. | ||
+ | |||
+ | Use the '' | ||
+ | |||
+ | < | ||
+ | def PersonProtocol := protocol: { | ||
+ | def name; | ||
+ | def age; | ||
+ | } named: `Person; | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | < | ||
+ | def tom := object: { | ||
+ | def name := " | ||
+ | def age() { 24 }; | ||
+ | } implements: PersonProtocol; | ||
+ | </ | ||
+ | |||
+ | You can also create a protocol from an object: | ||
+ | < | ||
+ | |||
+ | You can test protocol conformance in either of two styles: | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | You can also force a '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | More usage examples of structural types can be found in the unit test defined in the file '' | ||
+ | |||
+ | ==== Traits ==== | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | Using the '' | ||
+ | |||
+ | To define a " | ||
+ | < | ||
+ | trait: { | ||
+ | ... | ||
+ | } requiring: Protocol; | ||
+ | </ | ||
+ | |||
+ | The above code creates a trait that can only be composed into an object adhering to the specified protocol. To compose traits, use the following language construct: | ||
+ | |||
+ | < | ||
+ | object: { | ||
+ | use: { | ||
+ | import T1 exclude ...; | ||
+ | import T2 alias ...; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | Note that the place where '' | ||
+ | |||
+ | Usage examples can be found in the unit tests in the file '' | ||
+ | |||
+ | ===== Utilities ===== | ||
+ | |||
+ | The files in the '' | ||
+ | |||
+ | ==== Timing Utilities ==== | ||
+ | |||
+ | The module ''/ | ||
+ | |||
+ | < | ||
+ | def subscription := when: timeoutPeriod elapsed: { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | The milliseconds used to define the timeout period must be provided as a Java '' | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Additionally, | ||
+ | |||
+ | The timer module also defines a function '' | ||
+ | |||
+ | The timer module defines a small number of additional utility functions which can be found in the file '' | ||
+ | |||
+ | ==== Logging Framework ==== | ||
+ | |||
+ | ==== Object Inspector ==== | ||
+ | |||
+ | ==== Symbiosis Utilities ==== | ||
+ | |||
+ | ==== Miscellaneous ==== |
at/tutorial/appendix.txt · Last modified: 2021/09/24 10:28 by elisag