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:28] – Added tvcutsemat:tutorial:appendix [2008/07/10 15:42] – added tvcutsem
Line 102: Line 102:
 ==== Vector ==== ==== Vector ====
  
-A vector is a dynamically resizable AmbientTalk table (aka array). Vectors may be created as follows:+A vector is a dynamically resizable AmbientTalk table (aka array). Indexed reading from and writing to a vector is fast (O(1)). Adding elements to a vector is mostly fast, but sometimes requires a resize of the vectorVectors support the traditional stack operations ''push'' and ''pop'' and may be turned into sets by invoking their ''uniq'' method (note that a ''uniq''-ed vector is not permanently a Set: subsequent duplicates added to the vector will not be filtered). 
 + 
 +Vectors may be created as follows:
  
 <code> <code>
Line 112: Line 114:
  
 <code> <code>
-// returns the number of elements in the vector (not the capacity of the vector!)+// returns the number of elements in the vector (not its capacity!)
 length() length()
 +
 // returns whether the vector contains elements or not // returns whether the vector contains elements or not
 isEmpty() isEmpty()
 +
 // is the vector at max. capacity? // is the vector at max. capacity?
 atMaxCapacity() atMaxCapacity()
 +
 // return idx'th element or raise an IndexOutOfBounds exception // return idx'th element or raise an IndexOutOfBounds exception
 at(idx) at(idx)
 +
 // write idx'th element or raise IndexOutOfBounds exception // write idx'th element or raise IndexOutOfBounds exception
-//atPut(idx, val)+atPut(idx, val) 
 // iterate over the vector // iterate over the vector
 each: iterator, returns nil each: iterator, returns nil
 +
 // map a unary function over the vector, returns a new vector // map a unary function over the vector, returns a new vector
 map: fun map: fun
 +
 // accumulate a function with a given starting value // accumulate a function with a given starting value
 inject: init into: accum; inject: init into: accum;
 +
 // returns a new vector whose elements satisfy "cond" // returns a new vector whose elements satisfy "cond"
 filter: cond; filter: cond;
 +
 // implode a vector of character strings into one text string // implode a vector of character strings into one text string
 implode() implode()
 +
 // join a vector of character strings together with the given string // join a vector of character strings together with the given string
 join(txt) join(txt)
 +
 // returns a range [start,stop[ as a table // returns a range [start,stop[ as a table
 select(start, stop) select(start, stop)
-// appends an element to the back of the vector + 
-// returns the vector itself+// appends an element to the back of the vector. Returns the vector itself
 add(element) add(element)
 // alias for add(element) // alias for add(element)
-def <<(element)+<<(element) 
 // insert an element at a given position, causing subsequent elements to shift one pos to the right. Returns this vector // insert an element at a given position, causing subsequent elements to shift one pos to the right. Returns this vector
 insert(atPos, element) insert(atPos, element)
 +
 // delete the element at the given position, shifts all following elements one pos to the left. Returns the value of the element at the deleted position. // delete the element at the given position, shifts all following elements one pos to the left. Returns the value of the element at the deleted position.
 delete(atPos) delete(atPos)
 +
 // adds elements to the back of the vector // adds elements to the back of the vector
 push(element) push(element)
 +
 // deletes elements from the back of the vector // deletes elements from the back of the vector
 pop() pop()
-// return the index of the first element matching the given filter (a unary predicate), or nil if none is found+ 
 +// return the index of the first element matching the unary predicate or nil if none is found
 find: filter find: filter
 +
 // remove the given element from the vector, return true if the element was actually found and deleted, false otherwise // remove the given element from the vector, return true if the element was actually found and deleted, false otherwise
 remove(elt, cmp := defaultComparator) remove(elt, cmp := defaultComparator)
 +
 // remove all objects for which filter(elt) returns true // remove all objects for which filter(elt) returns true
 removeAll: filter removeAll: filter
 +
 // destructively appends otherVector to self. Returns this vector // destructively appends otherVector to self. Returns this vector
 addAll(otherVector) addAll(otherVector)
 +
 // empties the vector // empties the vector
 clear() clear()
 +
 // Return a new vector whose elements form the set-union of all elements in self U otherVector // Return a new vector whose elements form the set-union of all elements in self U otherVector
 union(otherVector, cmp := defaultComparator) union(otherVector, cmp := defaultComparator)
 +
 // Return a new vector whose elements form the set-intersection of all elements in self ^ otherVector // Return a new vector whose elements form the set-intersection of all elements in self ^ otherVector
 intersection(otherVector, cmp := defaultComparator) intersection(otherVector, cmp := defaultComparator)
 +
 // Return a new vector whose elements form the set-difference of self \ otherVector // Return a new vector whose elements form the set-difference of self \ otherVector
 difference(otherVector, cmp := defaultComparator) difference(otherVector, cmp := defaultComparator)
 +
 // Quicksort the vector in-place. The comparator defines the ordering among elements. // Quicksort the vector in-place. The comparator defines the ordering among elements.
 sort(cmp := { |e1,e2| e1 < e2 }) sort(cmp := { |e1,e2| e1 < e2 })
 +
 // Turn the vector into a set without duplicates in O(nlogn + n) // Turn the vector into a set without duplicates in O(nlogn + n)
 // The vector's ordering is lost (it becomes sorted) // The vector's ordering is lost (it becomes sorted)
 uniq(cmp := defaultComparator, ordercmp := {|e1,e2| e1 < e2 }) uniq(cmp := defaultComparator, ordercmp := {|e1,e2| e1 < e2 })
 +
 // return an element drawn randomly using a uniform distribution from the array or raise an EmptyVector exception. // return an element drawn randomly using a uniform distribution from the array or raise an EmptyVector exception.
 random() random()
 +
 // return a table containing all elements of the vector // return a table containing all elements of the vector
 asTable() asTable()
 </code> </code>
 +
 +The file ''at/collections/vector.at'' contains a unit tests that further helps to illustrate the usage of this Vector abstraction.
  
 ==== List ==== ==== List ====
 +
 +The module ''/.at.collections.list'' implements Scheme-like list datastructures. The module exports the prototype ''NIL'', which is bound to the empty list. Non-empty lists are defined as a chain of cons-cells.
 +
 +The list module defines two styles to manipulate cons-cells: an object-oriented and a functional style. The object-oriented style represents cons-cells as ''Cons'' prototypes. Given a cons-cell ''c'', a new one can be constructed by invoking ''c.new(car, cdr)''. The car and cdr part of the cons-cell can be extracted by means of ''c.car'' and ''c.cdr''.
 +
 +The functional style allows one to manipulate lists by means of the following functions:
 +
 +<code>
 +cons(car,cdr) -> a new cons-cell
 +car(conscell) -> the car
 +cdr(conscell) -> the cdr
 +list(@items) -> a cons-cell representing the head of a list
 +</code>
 +
 +Lists (cons-cells or the empty list) support the following operations:
 +
 +<code>
 +// accessors for car and cdr
 +car()
 +cdr()
 +
 +// the length of the list
 +length()
 +
 +// whether the list is empty or not
 +isEmpty()
 +
 +// returns the nth element of the list
 +nth(n)
 +
 +// apply a unary function to each element of the list
 +each: fun
 +
 +// apply a function to each element and its index in the list
 +// i.e. list.eachWithIndex: { |elt, idx| ... }
 +eachWithIndex: fun
 +
 +// map a unary function over the list, returning a new list
 + map: fun
 +
 +// accumulate a value over a list
 +inject: init into: accum
 +
 +// return a new list whose elements satisfy the unary predicate
 +filter: cond
 +
 +// does the list contain the element?
 +contains(elt, cmp := DEFAULTCOMPARATOR)
 +
 +// implode or join a list of text strings
 +implode()
 +join(txt)
 +
 +// drop the first n elements from the list
 +tail(n)
 +
 +// prepend an element to the list
 +add(elt)
 +
 +// insert an element in the list (functionally)
 +insert(atPos, element)
 +
 +// return a new list where the element atPos is deleted
 +delete(atPos)
 +
 +// functional append
 +append(aList)
 +
 +// return the index of the first matching element, or nil if none is found
 +find: filter
 +
 +// return the index in the list of the element or nil of not found
 +indexOf(elt, cmp := DEFAULTCOMPARATOR)
 +
 +// return a list where the given element is removed
 +remove(elt, cmp := DEFAULTCOMPARATOR)
 +
 +// return a new list where all objects for which filter(elt) is true are removed
 +removeAll: filter
 +
 +// convert the list into a table
 +asTable()
 +</code>
 +
 +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.
 +
 +===== Language Extensions =====
 +
 +The files in the ''at/lang'' directory define custom language features which mostly use AmbientTalk/2's reflective facilities to extend the language.
 +
 +==== Futures and Multifutures ====
 +
 +==== Dynamic Variables ====
 +
 +==== Ambient References ====
 +
 +==== Structural Types ====
 +
 +==== Traits ====
 +
 +
at/tutorial/appendix.txt · Last modified: 2021/09/24 10:28 by elisag