cue: a signal for action
cue: a thing said or done that serves as a signal to an actor or other performer to enter or to begin their speech or performance.
In Cobra code, the cue keyword is used to indicate a special method whose execution will be triggered under specific circumstances at run-time, such as object creation or enumeration via a for-loop.
Currently only "cue init" is fully supported.
- Initializer - cue init
- Destructor (destruction cleanup/Finalizer) - cue finalize
- Calculate an objects HashCode - cue hash as int
- Determine comparison operation - cue compare(other) as int
- Determine object equality - cue equals(other) as int
- Implement enumeration/iteration capability - cue enumerate as T*
- Others may be added as needed
# as for method definition but 'cue' replaces 'def'
cue <methodName> [as <returnType>] [is <AccessModifiers>] [has <Attributes>] [<DocString>] cue <methodName>(<paramList>) [as <returnType>] [is <AccessModifiers>] [has <Attributes>] [<DocString>]
Language systems generally have special hooks at the object level for various purposes such as comparisons, hash codes, enumeration, object construction, initialization and destruction Different languages use differing conventions and names for much the same ideas.
The original approach used the C#, VB, .Net naming except that constructors are done through "def init" which had the unfortunate consequence of conflicting with some third party libraries leading to some hacks in the compiler. Purportedly that approach also could not be extended to other backends (such as JVM) as they dont use the same exact method names as .NET.
The solution adopted was to introduce a new keyword cue used (instead of def) on methods that have or may have a special use or meaning and will be translated to the correct voodoo for whatever platform you're on (.NET, JVM, etc.)
Cues have some special rules about them, both in general and specific to particular cues:
- Cue declarations are exempt from needing "is override" on them.
- Most cues cannot be directly invoked external to the cue.
Normally however there is a canonical way in cobra to invoke the 'cued' capability or it
is invoked invisibly for you in the correct circumstances (hashcode)
"a = ClassName(args)" is the canonical way to construct and invoke an initializer
"a == b" is the canonical way to compare objects for equality, and
"for a in collection" is the canonical way to enumerate through the elements of a collection.
- One exception to "do not invoke cues directly" is that *within* the declaration of a cue, you can invoke it for purposes of implementation (e.g., base.init, .init, .thing.hash).
- A cue alters and adds to your class as needed to implement the cue.
For example the .enumerate cue when used on .NET will make your class implement IEnumerable and IEnumerable<of> while adding a method for each, for a total of two new methods.
This provides the capability of using your object in a for loop ("for a in mycollection, ...") and pass it where enumerables are expected ("List<of T>(...)").
- Cues cannot necessarily be reflected on by name at run-time as their run-time names may be different by platform (.NET "GetHashCode" vs. JVM "hashCode").
The intention is to provide implementations of the supported cues in a portable way between platforms and in some cases (like .enumerate) in a more convenient manner.
The init cue is used to denote an initializer for a class instance.
The initializer code is implicitly invoked on object construction to set the contents of an object instance to an initial state.
It doesnt return any value and is not inherited: i.e baseclass initialization must be done with an explicit call to a baseclass or sibling initializer
Constructor chaining can be done to another constructor in the same class
(usually to one with a different number or types of args)
or to a superclass constructor (using base.init)
- this call must be the first executable line in the initializer code body.
If an init cue is not specified the compiler runtime generates a (default) noArg constructor that does nothing.
Called implicitly on object destruction (at an indeterminate time).
Nominally responsible for release of any additional stored resources
e.g File handles, shared memory descriptors, sockets.
But please see the various platform notes (.Net and JVM) on issues with use of
destructors and finalizers and hints toward use of Disposal Interfaces instead (IDispose).
Hash Code Calculation
cue hash as int
Used to calculate a hash code (single unique id) for an object instance.
The platform Framework calls this implicitly when needed
(e.g. hash generation for Dictionary keys).
The .hash cue is also an exception to the 'should not call a cue directly' note above.
It is considered "externally visible" and can be invoked like an ordinary method.
see Object GetHashCode
cue compare(other) as int
Provide a comparison calculation for the ordering of instances of a class, this instance against the provided one.
The return value is 0 for equality, negative for .this < other, positive for .this > other
see IComparable(<T>).CompareTo Method
cue equals(other) as bool
Method used to determine if this instance is equal to another object.
Nominally called as a result of "a == b" expressions
Can be pretty much boilerplate along the following lines
cue equals(other [as Object]) as bool if this is other, return true if other inherits <!ThisClass> return <boolean comparisons on equality of instance fields> return false
see Object.equals method
Provide enumeration/iteration capability
cue enumerate as <Type>*
This cue provides an implementation of the Enumerable/Iterable? pattern for containers
such that the class supports the idea of enumeration/iteration.
i.e so that the cobra construct
for item in <myCollectionObject>
works such that item gets each item stored in the object one at a time.
It may (probably will) insert additional (boilerplate) code to provide exposure of this capability in the framework approved manner (Enumerator/Iterator?)
see IEnumerable and IEnumerable<of>
class Customer cue init(name as String) base.init _name = name cue finalize pass # release any held resources (file handles, sockets, ...) get name from var as String cue equals(other) as bool if this is other, return true if other inherits Customer return .name == other.name else return false cue hash as int return .name.hash
Currently only "cue init" is fully supported.
While you may specify access modifiers and return types in a cue the implementation may modify, augment or ignore these to conform to the platform requirements or restrictions
There is an original forum discussion post on cues.