Wiki
Version 5 (modified by Charles, 6 years ago)

--

Cues

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.

The cue keyword is used on some selected methods to indicate to the compiler that these methods are special, implement a 'special' behaviour or concept and will be treated specially to the system.

Cues supported include (or will include):

  • 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

See  Discussion Posting "Cue"

Grammar

# 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>]

Discussion

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)
    For example
    "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.

Initializer

cue init

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.

Destructor

cue finalize

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.

Platform .NET

see Object GetHashCode

Comparison

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

Platform .NET

see IComparable(<T>).CompareTo Method

Object equality

cue equals(other) as int

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

Platform .NET

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?)

Platform .NET

see IEnumerable and IEnumerable<of>

Examples

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

Notes

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

See also: LanguageTopics