at:tutorial:modular
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
at:tutorial:modular [2007/06/19 10:52] – tvcutsem | at:tutorial:modular [2013/05/17 20:24] (current) – adjusted tvcutsem | ||
---|---|---|---|
Line 57: | Line 57: | ||
The downside of such as scheme is that the absolute path name of the '' | The downside of such as scheme is that the absolute path name of the '' | ||
- | The [[at: | + | The [[at: |
< | < | ||
Line 64: | Line 64: | ||
Whenever a new actor is created by the AmbientTalk interpreter, | Whenever a new actor is created by the AmbientTalk interpreter, | ||
+ | |||
+ | Think of AmbientTalk' | ||
< | < | ||
Line 117: | Line 119: | ||
In this section, we describe how the '' | In this section, we describe how the '' | ||
+ | |||
==== 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 179: | Line 182: | ||
</ | </ | ||
- | So, '' | + | So, '' |
+ | |||
+ | Note that in AmbientTalk, | ||
+ | |||
+ | < | ||
+ | def Enumerable := object: { | ||
+ | def collect: clo { /* as before */ }; | ||
+ | def detect: pred { /* as before */ }; | ||
+ | def reject: pred { /* as before */ }; | ||
+ | def each: clo @Required; | ||
+ | } | ||
+ | </ | ||
==== Resolving conflicts: exclusion and aliasing ==== | ==== Resolving conflicts: exclusion and aliasing ==== | ||
Line 190: | Line 204: | ||
// do not import the slots collect: and detect: | // do not import the slots collect: and detect: | ||
import Enumerable exclude collect:, detect: | import Enumerable exclude collect:, detect: | ||
- | // do not import collect: and import reject: as remove | + | // do not import collect: and import reject: as remove: |
- | import Enumerable alias reject: := remove exclude collect: | + | import Enumerable alias reject: := remove: exclude collect: |
</ | </ | ||
If the compositor defines an alias for an imported slot, it is good practice to ensure that the compositor has (or imports) a slot with the original name as well. That way, if the trait object performs a self-send to invoke one of its own methods, it will find a matching slot in the compositor. If the compositor aliases a slot and does not define the slot itself, a lookup by the trait of the original slot name would fail. | If the compositor defines an alias for an imported slot, it is good practice to ensure that the compositor has (or imports) a slot with the original name as well. That way, if the trait object performs a self-send to invoke one of its own methods, it will find a matching slot in the compositor. If the compositor aliases a slot and does not define the slot itself, a lookup by the trait of the original slot name would fail. | ||
- | ===== Classifying objects using stripes | + | < |
+ | '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Moreover, all methods of the trait object annotated with '' | ||
+ | </ | ||
+ | |||
+ | ===== Classifying objects using type tags ===== | ||
In class-based languages, classes are a useful tool for categorising objects. Each object is an instance of some class, and sometimes it is useful to be able to ask to which class an object belongs. However, it is well-known by proponents of object-oriented programming that explicitly referring to the class of an object breaks that object' | In class-based languages, classes are a useful tool for categorising objects. Each object is an instance of some class, and sometimes it is useful to be able to ask to which class an object belongs. However, it is well-known by proponents of object-oriented programming that explicitly referring to the class of an object breaks that object' | ||
- | Nevertheless, | + | Nevertheless, |
< | < | ||
- | defstripe | + | deftype |
</ | </ | ||
- | Since a stripe | + | Since a type tag is an abstract type or category, it makes sense to define subtype relations on them. Also, since type tags do not carry an implementation, |
< | < | ||
- | defstripe | + | deftype |
- | defstripe | + | deftype |
- | defstripe | + | deftype |
</ | </ | ||
- | When defining an object, the object can be striped (tagged) with one or more stripes. | + | When defining an object, the object can be tagged with one or more type tags. |
< | < | ||
def Array := object: { | def Array := object: { | ||
... | ... | ||
- | } stripedWith: [ Indexable, Sortable ] | + | } taggedAs: [ Indexable, Sortable ] |
</ | </ | ||
- | Finally, the most useful operation defined on stripes | + | Finally, the most useful operation defined on type tags is the "type test": it allows objects to test whether an object is tagged with the appropriate |
< | < | ||
- | is: Array stripedWith: Indexable | + | is: Array taggedAs: Indexable |
>> true | >> true | ||
- | is: Array stripedWith: Ordered | + | is: Array taggedAs: Ordered |
>> true | >> true | ||
- | is: Array stripedWith: Set | + | is: Array taggedAs: Set |
>> false | >> false | ||
</ | </ | ||
- | The stripe | + | The type test determines whether an object //or one of its parents// is tagged |
- | The stripes | + | The type tags with which an object has been tagged can be retrieved by means of the '' |
< | < | ||
- | stripesOf: Array | + | tagsOf: Array |
- | >> [ <stripe: | + | >> [ <type tag: |
</ | </ | ||
< | < | ||
- | Stripes | + | 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 '' |
</ | </ | ||
- | ==== Native Stripes ==== | ||
- | The module ''/ | + | ==== Native Type Tags ==== |
+ | |||
+ | The module ''/ | ||
< | < | ||
- | is: 1 stripedWith: /.at.stripes.Number | + | is: 1 taggedAs: /.at.lang.types.Number |
>> true | >> true | ||
- | is: " | + | is: " |
>> true | >> true | ||
</ | </ | ||
- | The stripe | + | The type ''/ |
- | ==== Stripes | + | ==== Type tags as annotated message sends ==== |
- | In AmbientTalk, | + | In AmbientTalk, |
< | < | ||
- | obj.m(a, | + | obj.m(a, |
- | obj.m(a, | + | obj.m(a, |
</ | </ | ||
- | In the [[at: | + | In the [[at: |
===== Exception Handling ===== | ===== Exception Handling ===== | ||
Line 282: | Line 306: | ||
</ | </ | ||
- | The first argument is a closure to execute, delineating a dynamic piece of code to protect with the given exception handler. The third argument is a one-argument closure, invoked when an exception is caught of the right kind. The second argument is a stripe. By default, exceptions are handled based on their stripes. A hierarchy of stripes | + | The first argument is a closure to execute, delineating a dynamic piece of code to protect with the given exception handler. The third argument is a one-argument closure, invoked when an exception is caught of the right kind. The second argument is a type tag. By default, exceptions are handled based on their type tags. A hierarchy of type tags is used to classify exceptions. Exception handling in AmbientTalk is quite conventional: |
Raising an exception is done by means of the '' | Raising an exception is done by means of the '' | ||
Line 292: | Line 316: | ||
</ | </ | ||
- | Note that a new instance of an object named '' | + | Note that a new instance of an object named '' |
< | < | ||
- | defstripe | + | deftype |
- | def XDivisionByZero := lobby.at.exceptions.createException(DivisionByZero); | + | def XDivisionByZero := lobby.at.lang.exceptions.createException(DivisionByZero); |
</ | </ | ||
Line 317: | Line 341: | ||
// this is a first-class handler object | // this is a first-class handler object | ||
def canHandle(exc) { | def canHandle(exc) { | ||
- | is: exc stripedWith: DivisionByZero | + | is: exc taggedAs: DivisionByZero |
}; | }; | ||
def handle(exc) { | def handle(exc) { | ||
system.println(exc.message); | system.println(exc.message); | ||
}; | }; | ||
- | }) | + | } taggedAs: [/ |
</ | </ | ||
Line 335: | Line 359: | ||
calculateSomething(); | calculateSomething(); | ||
} catch: DivisionByZero using: { |e| | } catch: DivisionByZero using: { |e| | ||
- | system.println(e.message): | + | system.println(e.message); |
} catch: NoSolution using: { |e| | } catch: NoSolution using: { |e| | ||
calculateSomethingElse(); | calculateSomethingElse(); | ||
Line 344: | Line 368: | ||
Care has to be taken that handlers are listed in increasing order of " | Care has to be taken that handlers are listed in increasing order of " | ||
+ | |||
+ | ===== Escaping Continuations ===== | ||
+ | |||
+ | It is often useful to be able to abort the control flow within a method prematurely. In traditional imperative programming languages, this is done by means of a '' | ||
+ | |||
+ | < | ||
+ | def contains(tbl, | ||
+ | { |return| | ||
+ | 1.to: tbl.length do: { |i| | ||
+ | if: (tbl[i] == elt) then: { | ||
+ | return(true) | ||
+ | } | ||
+ | }; | ||
+ | false | ||
+ | }.escape() | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | When '' | ||
+ | |||
+ | As can be seen, an escaping continuation is more general than a return statement: the continuation is a first-class function object and can hence be passed on to other objects. Hence, it is possible to return from multiple nested function calls at once. | ||
+ | |||
+ | There is an important limitation to the use of escaping continuations. An escaping continuation is not a full-fledged continuation (such as the one provided by Scheme' |
at/tutorial/modular.1182243144.txt.gz · Last modified: 2007/06/19 16:05 (external edit)