Jump to content

Category talk:Wren-trait

From Rosetta Code

Source code

/* Module "trait.wren" */

/*  Cloneable is an abstract class which enables child classes to automatically be
    recognized as 'cloneable' by overriding the 'clone' method.
*/
class Cloneable {
    clone() { this } /* to be overridden by child class */
}

/*  CloneableSeq is an abstract class which enables child classes to automatically be
    recognized as both Sequences and 'cloneable' by overriding the 'clone' method.
*/
class CloneableSeq is Sequence {
    clone() { this } /* to be overridden by child class */
}

/*  Comparable is an abstract class which enables child clsses to automatically
    inherit the comparison operators by just overriding the 'compare' method.
    Comparable itself inherits from Cloneable though if one does not wish to override
    the 'clone' method, it will just return the current object by default.
*/
class Comparable is Cloneable {
    compare(other) {
        // This should be overridden in child classes to return -1, 0 or +1
        // depending on whether this < other, this == other or this > other.
    }

    < (other) { compare(other) <  0 }
    > (other) { compare(other) >  0 }
    <=(other) { compare(other) <= 0 }
    >=(other) { compare(other) >= 0 }
    ==(other) { compare(other) == 0 }
    !=(other) { compare(other) != 0 }
}

/*  Hashable is an abstract class which gives child classes a 'hash' property.
    This property returns a unique positive integer for each object which is
    generated when the property is first accessed. It should not be overridden
    by child classes. Hashable itself inherits from Cloneable though if one 
    does not wish to override the 'clone' method, it will just return the 
    current object by default.
*/
class Hashable is Cloneable {
    // Private property which returns the next hash and increments the counter.
    static next_ { __h = __h ? __h + 1 : 1 }

    // Returns the number of hashes that have been generated so far.
    static count { __h ? __h : 0 }

    // Returns the object's unique hash.
    hash { _h ? _h : _h = Hashable.next_ }
}

/*  HashableSeq is an abstract class which enables child classes to automatically be
    recognized as Sequences, 'cloneable' and 'hashable' by inheriting from CloneableSeq
    and giving them a unique 'hash' property as well as overriding the 'is' operator.
    The 'hash' is generated by the Hashable class when the property is first accessed.
    Neither it nor the 'is' operator should be overridden by child classes.
    Although HashableSeq inherits from CloneableSeq, if one does not wish to override
    the 'clone' method, it will just return the current object by default.
*/
class HashableSeq is CloneableSeq {
    // Returns the sequence's unique hash.
    hash { _h ? _h : _h = Hashable.next_ }

    // Extends the types normally recognized by 'is' to include Hashable.
    is(c) { c == this.type || c == Hashable || c == HashableSeq || 
            c == CloneableSeq || c == Sequence || c == Object }
}

/*  HashWrap provides any non-Hashable object with a Hashable wrapper. */
class HashWrap is Hashable {
    // Constructs a new HashWrap object from 'obj'.
    construct new(obj) {
        if (obj is Hashable) Fiber.abort("Object is already Hashable.")
        _obj = obj
    }

    // Returns the wrapped object.
    obj { _obj }

    // Returns the string representation of the wrapped object.
    toString { _obj.toString }
}

/*  ByRef wraps a value to enable it to be passed by reference to a method or function. */
class ByRef {
    // Constructs a new ByRef object.
    construct new(value) {
        _value = value
    }

    // Properties to get and set the value of the current instance.
    value     { _value }
    value=(v) { _value = v }

    // Returns the string representation of the current instance's value.
    toString { _value.toString }
}

/*  Const represents a group of individually named read-only values which are
    stored internally in a map. Any attempt to change such a value is ignored
    though they can be removed from the map.
*/
class Const {
    // Returns the value of 'name' if it is present in the internal map
    // or null otherwise.
    static [name] { (__cmap && __cmap.containsKey(name)) ? __cmap[name] : null }

    // Associates 'value' with 'name' in the internal map.
    // If 'name' is already in the map, the change is ignored.
    static [name]=(value) {
        if (!__cmap) __cmap = {}
        if (!__cmap.containsKey(name)) {
            __cmap[name] = value
        }
    }

    // Removes 'name' and its associated value from the internal map and returns
    // that value. If 'name' was not present in the map, returns null.
    static remove(name) { __cmap.remove(name) }

    // Returns a list of the entries (name/value pairs) in the internal map.
    static entries { __cmap.toList }
}

/*  Var represents a group of individually named read/write values which are
    stored internally in a map. It can be used to simulate the creation of
    variables at runtime. It can also be used to allow variable names which would
    otherwise be illegal in Wren such as those which include non-ASCII characters.
*/
class Var {
    // Returns the value of 'name' if it is present in the internal map
    // or null otherwise.
    static [name] { (__vmap && __vmap.containsKey(name)) ? __vmap[name] : null }

    // Associates 'value' with 'name' in the internal map.
    // Any existing value is replaced.
    static [name]=(value) {
        if (!__vmap) __vmap = {}
        __vmap[name] = value
    }

    // Removes 'name' and its associated value from the internal map and returns
    // that value. If 'name' was not present in the map, returns null.
    static remove(name) { __vmap.remove(name) }

    // Returns a list of the entries (name/value pairs) in the internal map.
    static entries { __vmap.toList }
}

/* TypedVar is similar to Var except that simulated variables always retain the
   same type as they had when they were originally created.
*/
class TypedVar {
    // Returns the value of 'name' if it is present in the internal map
    // or null otherwise.
    static [name] { (__vmap && __vmap.containsKey(name)) ? __vmap[name] : null }

    // Associates 'value' with 'name' in the internal map.
    // Any existing value is replaced. However, it is an error to attempt to replace
    // an existing value with a value of a different type.
    static [name]=(value) {
        if (!__vmap) __vmap = {}
        if (!__vmap.containsKey(name)) {
            __vmap[name] = value
        } else {
            var vtype = value.type
            var mtype = __vmap[name].type
            if (vtype != mtype) {
                Fiber.abort("Expecting an item of type %(mtype), got %(vtype).")
            } else {
                __vmap[name] = value
            }
        }
    }

    // Removes 'name' and its associated value from the internal map and returns
    // that value. If 'name' was not present in the map, returns null.
    static remove(name) { __vmap.remove(name) }

    // Returns a list of the entries (name/value pairs) in the internal map.
    static entries { __vmap.toList }
}
Cookies help us deliver our services. By using our services, you agree to our use of cookies.