quarta-feira, 14 de novembro de 2007

The End

Since no one really reads, this blog is over.

The house fell for once.

segunda-feira, 5 de novembro de 2007

Lists with Caché

Caché Lists - an object oriented approach

Unlike Java, the Intersystems Caché doesn't have large API to manipulate data structures of collections (lists, queues, sets, etc). In fact, when we work with objects in Caché, we can rely only on two pre-defined structures: lists and arrays.

For Caché, lists are, as the name implies, lists of objects (instances of classes you write) r lists of basic data types (as %Integer or %Float). Each element of a list is associated with a position in it. Caché lists are very similar to Java lists (comparing with List interface, about implementation, we can not make good comparison, since Java can have lots of implementations, as ArrayList orLinkedList).

With Caché, the abstract class %Collection.AbstractList gives us the basic interface to work with lists. Adapted from docs, the code snippet below shows how to create a list, 4 elements insertions, and how to iterate the list:


; creates new list
Set list=##class(%ListOfDataTypes).%New()
; here we add four elements in the list, four strings
Do list.Insert("DArtagnan")
Do list.Insert("Athos")
Do list.Insert("Porthos")
Do list.Insert("Aramis")
; how to iterate the list
For i=1:1:list.Count() Write list.GetAt(i),!



Caché arrays are a little bit different. They seem a lot like Java Map's interface. A Caché array needs, besides an element, a key to associate with it. Through this key, you can access the element in the structure. This kind of structure are useful to implement hash tables, as Java's Hashtable class.

As examples are the best way we can learn, below there is one, adapted from the documentation on class %Collection.AbstractArray, the 'interface' of Caché arrays:

; creates new array 
Set arr=##class(%ArrayOfDataTypes).%New()
; put itens in array - the second parameter is the 'key'
Do arr.SetAt("red","color")
Do arr.SetAt("large","size")
Do arr.SetAt("expensive","price")
; how to iterate arrays
Set key=""
For Set value=arr.GetNext(.key) Quit:key="" Write key,":",value,!



(Just pay attention to SetAt method, similar to java.util.Map's put. The order of parameters is inverted in those two. As put has the key as first parameter, SetAt the key is the second.)

With both examples above, we use basic data types (%String, in both cases) as elements in lists and arrays, but we could have used objects. To use objects, we can just swap %ListOfDataTypes and %ArrayOfDataTypes for %ListOfObjects and %ArrayOfObjects.

When we use collections as classes properties, we can explicitly declare the property as an object of Array/List classes or we can declare them as below:


; a %String list
; instead: Property Colors As %ListOfDataTypes
Property Colors As List Of %String


Just keep in mind that arrays and lists classes are classes of Serial type, i.e., they inherit from %SerialObject, therefore, they are 'serialized' inside other classes when they are persisted. If a list is too big, or even if the list has not that much elements, but the elements are %SerialObject too, there is a chance to occur a error.

Consider the class below:


Class Test.Bang Extends %Persistent [ ClassType = persistent ] {

Property alist As list Of %String;

ClassMethod test(amount as %Integer)
{
set a = ##class(Test.Bang).%New()
w a.%Save()
For i=1:1:amount {
do a.alist.Insert(i)
}
w a.%Save()
}
}


You can test calling "test method" with different values. With Caché 5.2, if you call "do ##class(Test.Bang).test(10000)", you can check the error. I just heard that newer versions, as 2007, the maximum string size was increased, so this kind of error will occur less frequently (although I didn't check this info myself).