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 14:51] – added tvcutsemat:tutorial:appendix [2008/07/10 15:29] – Added tvcutsem
Line 261: Line 261:
 join(txt) join(txt)
  
-// return a range [start,stop] represented as a list +// drop the first n elements from the list 
-select(start, stop)+tail(n)
  
 // prepend an element to the list // prepend an element to the list
Line 293: Line 293:
  
 The file ''at/collections/list.at'' contains a unit test that further illustrates the usage of the list datastructure. The file ''at/collections/list.at'' contains a unit test that further illustrates the usage of the list datastructure.
 +
 +
 +===== Top-level functions =====
 +
 +The file ''at/init/init.at'' shipped with the AmbientTalk/2 system library contains the code that is evaluated on startup within //every// actor created in the system. Because the definitions are evaluated in every actor's top-level scope, these  definitions will be globally visible in every file. Below, we describe the standard functionality provided by AmbientTalk/2's default ''init'' file.
 +
 +==== Asynchronous control structures ====
 +
 +The ''init'' file defines a number of useful control structures that operate asynchronously. 
 +
 +''loop:'' defines an infinite asynchronous loop. That is, the block closure is executed, then asynchronously applied again:
 +<code>
 +loop: {
 +  ...
 +}
 +</code>
 +
 +An ''if''-test on a future for a boolean:
 +<code>
 +whenTrue: booleanFuture then: { ... } else: { ... }
 +</code>
 +
 +Asynchronous while loop over future-type conditional:
 +<code>
 +asLongAs: { /* asynchronous computation returning a future */ } do: { ... }
 +</code>
 +
 +==== Mobile code ====
 +
 +The function ''script:carrying:'' can be used to define a "pass-by-copy" closure, as follows:
 +
 +<code>
 +def mobileAdder(x) {
 +  script: { |n| x + n } carrying: [`x]
 +}
 +</code>
 +
 +A call to ''mobileAdder(5)'' returns a closure which, when applied to a number, returns that number incremented with 5. Unlike regular closures, which are pass-by-far-reference when passing them to another actor, the above closure is pass-by-copy. The result is that a remote actor can apply the closure synchronously. The catch is that for this to work, the closure must specifically list all of its lexically free variables in the ''carrying:'' parameter. These variables will be copied along with the closure when it is parameter-passed.
 +
 +The constructor function ''isolate:passAs:'' allows you to define an isolate object with a custom serialization strategy. For example,
 +
 +<code>
 +def foo := 42;
 +def i := isolate: {
 +  ...
 +} passAs: { |foo|
 +  /.some.Object.new(foo);
 +}
 +</code>
 +
 +The above code defines an isolate object ''i'' which, when passed between actors, becomes a ''some.Object'' on the other side. Note that state (''foo'' in the example) can be transferred as usual via the parameter list of the closure.
 +
 +===== Custom Exceptions =====
 +
 +The module ''/.at.exceptions'' defines a number of auxiliary methods which can be used to define one's own custom exceptions. Here is how to define a custom exception ''FooException''. First, define a new type tag with which clients of your code can catch the exception:
 +
 +<code>
 +deftype FooException;
 +</code>
 +
 +Next, define a prototype exception object using the ''createException'' function exported by the exception module. As a convention, an exception prototype object is prefixed with ''X'':
 +
 +<code>
 +def XFooException := createException(FooException);
 +</code>
 +
 +''XFooException'' is now bound to an object which is tagged with the given type tag, and which implements two methods: ''stackTrace'', which returns an AmbientTalk stack trace for the exception, and ''message'', which returns a string indicating what went wrong. The object also has a constructor taking a new message as an argument. You can now raise your custom exception as follows:
 +
 +<code>
 +raise: XFooException.new("reason for what went wrong");
 +</code>
 +
 +If your custom exception requires additional state, you can define it as an extension of the prototype exception. If you define a custom constructor, do not forget to initialise the parent object, as follows:
 +
 +<code>
 +deftype IndexOutOfBounds;
 +def XIndexOutOfBounds := createException(IndexOutOfBounds) with: {
 +  def min;
 +  def max;
 +  def idx;
 +  def init(min, max, idx) {
 +    super^init("Index out of bounds: given " + idx + " allowed: [" + min + "," + max + "]");
 +    self.min := min;
 +    self.max := max;
 +    self.idx := idx;
 +  }; 
 +}
 +</code>
 +
 +The exception module also exports an auxiliary function ''error(msg)'' which can be used to raise a "quick and dirty" runtime exception with a given message. It also exports the prototypes of a number of standard exceptions that can be raised by the language runtime itself.
at/tutorial/appendix.txt · Last modified: 2021/09/24 10:28 by elisag