User Tools

Site Tools


at:tutorial:modular

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
at:tutorial:modular [2008/09/17 15:53]
tvcutsem *
at:tutorial:modular [2013/05/17 20:24] (current)
tvcutsem adjusted
Line 64: Line 64:
  
 Whenever a new actor is created by the AmbientTalk interpreter, it uses the entries in the object path to initialize the ''lobby'' object of the actor. Hence, by starting up the interpreter as shown above, executing ''lobby.lib'' in any actor returns a reference to a namespace object bound to the ''examples'' directory. This effectively removes absolute path names from AmbientTalk source code and even enables you to quickly reconfigure AmbientTalk code to use other libraries by loading the code using another object path. Whenever a new actor is created by the AmbientTalk interpreter, it uses the entries in the object path to initialize the ''lobby'' object of the actor. Hence, by starting up the interpreter as shown above, executing ''lobby.lib'' in any actor returns a reference to a namespace object bound to the ''examples'' directory. This effectively removes absolute path names from AmbientTalk source code and even enables you to quickly reconfigure AmbientTalk code to use other libraries by loading the code using another object path.
 +
 +Think of AmbientTalk's object path as the equivalent of Java's classpath.
  
 <note> <note>
Line 117: Line 119:
  
 In this section, we describe how the ''import'' statement can also be used to compose multiple objects. In this respect, objects can be regarded as //traits//. [[http://www.iam.unibe.ch/~scg/Research/Traits|Traits]] are a model of object-oriented software composition, similar to (but more advanced than) mixins. A trait can be regarded as a kind of abstract class, which does not define any state, which //provides// a set of methods and which //requires// a set of methods in order to be instantiated. In a class-based language, a class may //use// one or more traits. The class takes on the role of compositor and is responsible for ensuring that, once all traits have been imported, each trait its required interface is provided by the class or other imported traits. A trait is almost literally a piece of code which can be "copy-pasted" into a class. In this section, we describe how the ''import'' statement can also be used to compose multiple objects. In this respect, objects can be regarded as //traits//. [[http://www.iam.unibe.ch/~scg/Research/Traits|Traits]] are a model of object-oriented software composition, similar to (but more advanced than) mixins. A trait can be regarded as a kind of abstract class, which does not define any state, which //provides// a set of methods and which //requires// a set of methods in order to be instantiated. In a class-based language, a class may //use// one or more traits. The class takes on the role of compositor and is responsible for ensuring that, once all traits have been imported, each trait its required interface is provided by the class or other imported traits. A trait is almost literally a piece of code which can be "copy-pasted" into a class.
 +
  
 ==== import as trait composition ==== ==== import as trait composition ====
Line 160: Line 163:
   };   };
   def each: clo {   def each: clo {
-    start.to: end do: clo+    start.to: end-1 do: clo
   };   };
 }; };
Line 180: Line 183:
  
 So, ''import'' defines small methods which delegate the request to the original trait (using AmbientTalk's support for [[:at:tutorial:objects#first-class_delegation|explicit delegation]]). The use of delegation is crucial here: it means that within the context of the trait, ''self'' is bound to the object using the trait. Hence, when ''reject:'' is invoked on a ''Range'' object, ''Enumerable'''s ''self.each:'' will refer to the correct implementation of ''Range''. So, ''import'' defines small methods which delegate the request to the original trait (using AmbientTalk's support for [[:at:tutorial:objects#first-class_delegation|explicit delegation]]). The use of delegation is crucial here: it means that within the context of the trait, ''self'' is bound to the object using the trait. Hence, when ''reject:'' is invoked on a ''Range'' object, ''Enumerable'''s ''self.each:'' will refer to the correct implementation of ''Range''.
 +
 +Note that in AmbientTalk, a trait does not need to explicitly specify the set of methods which it "requires" from its composite. However, for documentation purposes, it is often very useful to explicitly state the methods on which a trait depends. One may do so by defining those methods in the trait, and annotating them with the ''@Required'' type tag (which is predefined in the ''lobby.at.lang.types'' module). These methods will //not// be imported when the trait is used by a composite object (otherwise they would cause a conflict with the real implementation methods in the composite). Below is an example of how the ''Enumerable'' trait can be modified to explicitly state its required methods:
 +
 +<code>
 +def Enumerable := object: {
 +  def collect: clo { /* as before */ };
 +  def detect: pred { /* as before */ };
 +  def reject: pred { /* as before */ };
 +  def each: clo @Required;
 +}
 +</code>
  
 ==== Resolving conflicts: exclusion and aliasing ==== ==== Resolving conflicts: exclusion and aliasing ====
Line 200: Line 214:
   * ''super'' (the parent object) because this slot is present in //all// AmbientTalk objects.   * ''super'' (the parent object) because this slot is present in //all// AmbientTalk objects.
   * ''~'' (the current namespace), because this slot is present in //all// namespace objects.   * ''~'' (the current namespace), because this slot is present in //all// namespace objects.
 +
 +Moreover, all methods of the trait object annotated with ''@Required'' are automatically excluded upon ''import''.
 </note> </note>
  
Line 251: Line 267:
 Type tags can best be compared to empty Java interface types. Such empty interfaces are sometimes used in Java purely for the purposes of marking an object. Examples are ''java.io.Serializable'' and ''java.lang.Cloneable''. An empty interface type can be implemented by any class (object) and hence only serves the purpose of distinguishing objects by type (by means of ''instanceof'' in Java). Type tags can best be compared to empty Java interface types. Such empty interfaces are sometimes used in Java purely for the purposes of marking an object. Examples are ''java.io.Serializable'' and ''java.lang.Cloneable''. An empty interface type can be implemented by any class (object) and hence only serves the purpose of distinguishing objects by type (by means of ''instanceof'' in Java).
 </note> </note>
 +
  
 ==== Native Type Tags ==== ==== Native Type Tags ====
  
-The module ''/.at.types'' shipped with the system library contains the type definitions of the native data types of the interpreter. These type tags can be used to perform type tests on objects, for example:+The module ''/.at.lang.types'' shipped with the system library contains the type definitions of the native data types of the interpreter. These type tags can be used to perform type tests on objects, for example:
  
 <code> <code>
-is: 1 taggedAs: /.at.types.Number+is: 1 taggedAs: /.at.lang.types.Number
 >> true >> true
-is: "foo" taggedAs: /.at.types.Text+is: "foo" taggedAs: /.at.lang.types.Text
 >> true >> true
 </code> </code>
  
-The type ''/.at.types.Isolate'' can be used to mark an object as an isolate. Isolate objects are similar to serializable Java objects. They are explained when introducing concurrent programming in [[at:tutorial:actors|a later chapter]].+The type ''/.at.lang.types.Isolate'' can be used to mark an object as an isolate. Isolate objects are similar to serializable Java objects. They are explained when introducing concurrent programming in [[at:tutorial:actors|a later chapter]].
  
 ==== Type tags as annotated message sends ==== ==== Type tags as annotated message sends ====
Line 275: Line 292:
  
 In the [[at:tutorial:actors|chapter on actors]] we use this feature to distinguish purely asynchronous message sends from so-called //future-type// message sends. If the message send is annotated with the ''FutureMessage'' type tag, the asynchronous send returns a future, otherwise it returns ''nil''. In the [[at:tutorial:actors|chapter on actors]] we use this feature to distinguish purely asynchronous message sends from so-called //future-type// message sends. If the message send is annotated with the ''FutureMessage'' type tag, the asynchronous send returns a future, otherwise it returns ''nil''.
 +
  
 ===== Exception Handling ===== ===== Exception Handling =====
Line 298: Line 316:
 </code> </code>
  
-Note that a new instance of an object named ''XDivisionByZero'' is raised, not the type tag ''DivisionByZero'' itself. An exception is any object that is tagged with (a subtype of) the ''lobby.at.types.Exception'' type tag. By convention, an exception should have the fields ''message'' and ''stackTrace''. The exception module found under ''lobby.at.exceptions'' contains an auxiliary function named ''createException'' which takes a type tag as argument and returns a new prototype exception object. For example:+Note that a new instance of an object named ''XDivisionByZero'' is raised, not the type tag ''DivisionByZero'' itself. An exception is any object that is tagged with (a subtype of) the ''lobby.at.lang.types.Exception'' type tag. By convention, an exception should have the fields ''message'' and ''stackTrace''. The exception module found under ''lobby.at.lang.exceptions'' contains an auxiliary function named ''createException'' which takes a type tag as argument and returns a new prototype exception object. For example:
  
 <code> <code>
-deftype DivisionByZero <: lobby.at.types.Exception; +deftype DivisionByZero <: lobby.at.lang.types.Exception; 
-def XDivisionByZero := lobby.at.exceptions.createException(DivisionByZero);+def XDivisionByZero := lobby.at.lang.exceptions.createException(DivisionByZero);
 </code> </code>
  
Line 328: Line 346:
     system.println(exc.message);     system.println(exc.message);
   };   };
-})+taggedAs: [/.at.lang.types.Handler])
 </code> </code>
  
Line 358: Line 376:
 def contains(tbl, elt) { def contains(tbl, elt) {
   { |return|   { |return|
-    1.to: tbl.length + 1 do: { |i|+    1.to: tbl.length do: { |i|
       if: (tbl[i] == elt) then: {       if: (tbl[i] == elt) then: {
         return(true)         return(true)
at/tutorial/modular.1221659584.txt.gz · Last modified: 2008/09/17 17:13 (external edit)