User Tools

Site Tools


at:tutorial:appendix

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
at:tutorial:appendix [2008/07/10 16:08] – * tvcutsemat:tutorial:appendix [2008/07/10 16:39] – added tvcutsem
Line 392: Line 392:
 === Futures === === Futures ===
  
-The module ''/.at.lang.futures'' provides support for futures. Futures have already been described as part of the [[concurreny|concurrency]] section in the tutorial.+The module ''/.at.lang.futures'' provides support for futures. Futures have already been described as part of the [[:at:tutorial:actors#futures|concurrency]] section in the tutorial.
  
 The module exports the type tags ''OnewayMessage'', ''FutureMessage'' and ''Due'': The module exports the type tags ''OnewayMessage'', ''FutureMessage'' and ''Due'':
Line 439: Line 439:
 </code> </code>
  
-This listener is invoked whenever the future is resolved with a new value. Its code can thus be executed multiple times.+The above listener is invoked whenever the future is resolved with a new value. Its code can thus be executed multiple times.
  
 <code> <code>
Line 447: Line 447:
 </code> </code>
  
-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.+The above listener is invoked if all results have been gathered (only possible if the maximum number of results is known) or when the ''timeout'' period associated with the future has elapsed. ''values'' refers to a table of all resolved values. 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 table.
  
 Note the following properties of multifutures: Note the following properties of multifutures:
Line 464: Line 464:
  
 ==== Dynamic Variables ==== ==== Dynamic Variables ====
 +
 +The module ''/.at.lang.dynvars'' provides support for defining and using 'Dynamic Variables'. Dynamic variables 'simulate' dynamically scoped variables and are often used to parameterize large parts of code. For example, the 'current output stream'. A dynamic variable has the advantage over a simple global variable that it can only be assigned a value for the extent of a block of code.
 +
 +A dynamic variable can be defined as follows:
 +<code>
 +def name := dynamicVariable: initialValue;
 +</code>
 +
 +It can be read as follows:
 +<code>
 +?name or name.value
 +</code>
 +
 +It can be assigned only within a limited dynamic scope, as follows:
 +<code>
 +with: name is: newval do: { code }
 +// or
 +name.is: newval in: { code }
 +</code>
 +
 +When ''code'' terminates (either normally or via an exception), the dynamic variable is automatically reset to its previous value.
 +
 +By convention, we prefix the names of dynamic variables with a ''d'', e.g. ''dTimeoutPeriod''. This makes it easier to remember to access these variables by means of ''?'' or ''.value''.
 +
 +You can find more usage examples of dynamic variables in the unit test included in the file ''at/lang/dynvars.at''.
  
 ==== Ambient References ==== ==== Ambient References ====
 +
 +Ambient references are defined in the module ''/.at.lang.ambientrefs'' . An ambient reference is a special kind of far reference which refers to an ever-changing collection of objects of a certain type. For example:
 +
 +<code>
 +import /.at.lang.ambientrefs;
 +deftype Printer;
 +def printers := ambient: Printer;
 +</code>
 +
 +In the above code, ''printers'' refers to all nearby objects exported by means of  the ''Printer'' type tag. An more in-depth explanation of ambient references can be found on the [[:research:ambientrefs|research page of ambient references]].
 +
 +Ambient references ship with two so-called "implementation modules": the module ''/.at.ambient.ar_extensional_impl'' and the module ''/.at.m2mi.ar_intensional_impl''. By default, the extensional implementation is used, but this can be changed by passing the desired implementation module as a parameter to the ''/.at.lang.ambientrefs'' module.
  
 ==== Structural Types ==== ==== Structural Types ====
 +
 +The module ''/.at.lang.structuraltypes'' implements a small library to use structural typing. The library allows for the creation of 'protocols', which are first-class structural types. A structural type is simply a set of selectors. An object o conforms to a protocol P <=> for all selectors s of P, o respondsTo s where respondsTo is determined by o's mirror.
 +
 +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 ''protocol:'' function to create a new protocol:
 +
 +<code>
 +def PersonProtocol := protocol: {
 +  def name;
 +  def age;
 +} named: `Person;
 +</code>
 +
 +The ''`Person'' argument is used to give the protocol a name simply for display purposes. The ''object:implements:'' function automatically checks whether an object conforms to any declared types:
 +
 +<code>
 +def tom := object: {
 +  def name := "Tom";
 +  def age() { 24 };
 +} implements: PersonProtocol;
 +</code>
 +
 +You can also create a protocol from an object:
 +<code>def tomsProtocol := protocolOf: tom;</code>
 +
 +You can test protocol conformance in either of two styles:
 +  * ''does: tom implement: PersonProtocol'' => true or false
 +  * ''PersonProtocol <? tom'' => true or false
 +
 +You can also force a ''StructuralTypeMismatch'' exception to be raised if the object does not conform to the type:
 +  *  ''ensure: tom implements: PersonProtocol'' => true or exception
 +  *  ''PersonProtocol.checkConformance(tom)'' => true or exception
 +
 +More usage examples of structural types can be found in the unit test defined in the file ''at/lang/structuraltypes.at''.
  
 ==== Traits ==== ==== Traits ====
 +
 +The module ''/.at.lang.traits'' exports a small library to use AmbientTalk's traits in a more structured manner. In the literature, traits are described as reusable components with two interfaces: an interface of methods that are //provided// by the trait //to// the composite and an interface of methods that are //required// by the trait //from// the composite. AmbientTalk's traits only make the provided interface explicit. The required interface remains implicit and unchecked at composition time.
 +
 +Using the ''traits'' module, a trait can specify that it requires its composite to adhere to a certain protocol (i.e. a structural type, cf. the previous section). Using traits in this way requires an explicit composition step where the trait's requirements are checked.
 +
 +To define a "structured" trait, define your  trait objects as follows:
 +<code>
 +trait: {
 +  ...
 +} requiring: Protocol;
 +</code>
 +
 +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:
 +
 +<code>
 +object: {
 +  use: {
 +    import T1 exclude ...;
 +    import T2 alias ...;
 +  }
 +}
 +</code>
 +
 +The ''use:'' block can **only** include ''import'' statements. It simply executes the ''import'' statements, but in addition checks whether the composite, //after// having imported all of its traits, provides all of the methods specified in the required protocol of its imported traits.
 +
 +Note that the place where ''use:'' is used inside an object matters: if one of the traits requires a method ''m()'' that is defined only later in the composite, the check will fail. To avoid this, place the ''use:'' block at the bottom of the object declaration.
 +
 +Usage examples can be found in the unit tests in the file ''at/lang/traits.at''.
at/tutorial/appendix.txt · Last modified: 2021/09/24 10:28 by elisag