Wiki
Version 21 (modified by Charles, 12 years ago)

--

Standard Library Class Extension methods

The Cobra standard library adds the following extension methods to existing classes. This enables convenient expressions such as:

for item in someList.sorted.reversed
    print item

for i, item in someList.sorted.numbered
    print i, item   # i will be 0, 1, 2, ...

Here they are:

namespace Cobra.Core

    extend System.Object

        def typeOf as System.Type
            """
            Return the Type of the object this is called on. 
            Using .typeOf is portable between platforms in contrast to CLR .getType and JVM .getClass.
            """

        def toTechString as String
            """
            Generate a 'technical' string representation of the object suitable for inspection and debugging.
            Used for AssertExceptions (and subclasses such as RequireException) and the `trace` statement.
            It provides more information about collections and enumerations and recovers from exceptions
            when making strings so that debugging can proceed.
            """

        def toPrintString as String
            """
            Generate a string representation of the object suitable for printing.
            Strings are only quoted if they are inside collections such as a list or dictionary.
            """     


    extend String
    
        def before(sep as String) as String
            test
                s = 'abc|de'
                assert s.before('|') == 'abc'
                assert s.before('=') == 'abc|de'
                assert '|abcde'.before('|') == ''
                assert 'abcde|'.before('|') == 'abcde'

        def after(sep as String) as String
            test
                s = 'abc|de'
                assert s.after('|') == 'de'
                assert s.after('=') == ''
                assert '|abcde'.after('|') == 'abcde'
                assert 'abcde|'.after('|') == ''

        def capitalized as String
            """
            Returns the string with the first character capitalized.
            Returns a blank string for a blank string.
            """
            ensure
                result.length == .length
                result.length implies result[0] == result[0].toUpper
            test
                assert 'chuck'.capitalized == 'Chuck'
                assert 'Chuck'.capitalized == 'Chuck'
                assert ''.capitalized == ''
                assert ' foo'.capitalized == ' foo'
                assert 'f'.capitalized == 'F'
                assert '1aoeu'.capitalized == '1aoeu'

        def count(c as char) as int
            test
                assert ''.count(c'x')==0
                assert 'x'.count(c'x')==1
                assert 'X'.count(c'x')==0  # case sensitive
                assert ' ! ! '.count(c'!')==2

        def count(substring as String) as int
            """ Return a count of the number of occurrences of the substring in this string. """
            test
                assert ''.count('aoeu') == 0
                assert 'x'.count('x') == 1
                assert 'xyxy'.count('xy') == 2
                assert 'xyxy'.count('a') == 0

        def isCapitalized as bool
            test
                assert 'Aoeu'.isCapitalized
                assert 'Zaoeu'.isCapitalized
                assert not 'aoeu'.isCapitalized
                assert not ''.isCapitalized
                assert not '1234'.isCapitalized

        def md5HashInHex as String
            ensure
                result.length == 32
            test
                assert 'Black holes and revelations.'.md5HashInHex == '95b141d670c19f2f20a820751897b9c6'

        def split(chars as List<of char>) as List<of String>
            test
                s = 'a,b:c:d,e,f'
                assert s.split([c',', c':']) == ['a', 'b', 'c', 'd', 'e', 'f']
    
        def split(chars as IList<of char>) as List<of String>

        def splitLines as List<of String>
            return .splitLines(false)
        
        def splitLines(keepEnds as bool) as List<of String>
            """
            Returns the string split into lines, recognizing the various line endings (posix, dos/http, old mac) even if mixed within the same string.
            """
            test
                cases = [
                    ['', false, []],
                    ['   ', false, ['   ']],
                    ['x', false, ['x']],
                    ['x y', false, ['x y']],

                    ['a\n', false, ['a']],
                    ['a\n', true, ['a\n']],
                    ['a\nb', false, ['a', 'b']],
                    ['a\nb', true, ['a\n', 'b']],
                    ['a\nb\n', false, ['a', 'b']],
                    ['a\nb\n', true, ['a\n', 'b\n']],

                    ['a\r', false, ['a']],
                    ['a\r', true, ['a\r']],
                    ['a\rb', false, ['a', 'b']],
                    ['a\rb', true, ['a\r', 'b']],
                    ['a\rb\r', false, ['a', 'b']],
                    ['a\rb\r', true, ['a\r', 'b\r']],

                    ['a\r\n', false, ['a']],
                    ['a\r\n', true, ['a\r\n']],
                    ['a\r\nb', false, ['a', 'b']],
                    ['a\r\nb', true, ['a\r\n', 'b']],
                    ['a\r\nb\r\n', false, ['a', 'b']],
                    ['a\r\nb\r\n', true, ['a\r\n', 'b\r\n']],
                
                    ['a\r\n\r\n', false, ['a', '']],
                    ['a\r\n\r\n', true, ['a\r\n', '\r\n']],
                    ['a\r\n\r\n\r\n', false, ['a', '', '']],
                    ['a\r\n\r\n\r\n', true, ['a\r\n', '\r\n', '\r\n']],
                
                    ['a\rb\nc\r\nd', false, ['a', 'b', 'c', 'd']],
                    ['a\rb\nc\r\nd', true, ['a\r', 'b\n', 'c\r\n', 'd']],
                ]
                for a, b, c in cases
                    input = a to String
                    keepEnds = b to bool
                    expected = c
                    # trace input, keepEnds, expected
                    actual = input.splitLines(keepEnds)
                    assert actual == expected

        def splitWords as List<of String>
            test
                # preliminary:
                assert 'foo bar'.split == ['foo', 'bar']
                assert 'foo  bar'.split == ['foo', '', 'bar']  # undesireable
                assert 'foo   bar'.split == ['foo', '', '', 'bar']  # undesireable
                assert Regex(r'\s+').split('foo  bar\r\nbaz') == ['foo', 'bar', 'baz']
                # this method:
                assert 'foo  bar\r\nbaz'.splitWords == ['foo', 'bar', 'baz']

    extend System.Collections.IList
    
        def addRange(items as System.Collections.IEnumerable)

        def swap(i as int, j as int)
            require
                i >= -.count and i < .count
                j >= -.count and j < .count
            ensure
                old this[i] == this[j]
                old this[j] == this[i]
                .count == old.count


    extend IEnumerable<of T>

        def toList as List<of T>
            return List<of T>(this)


    extend IList<of T>
    
        def addRange(items as IEnumerable<of T>)

        def concated(other as IList<of T>?) as IList<of T>
            """
            Returns a new list with the contents of this list and the other.
            Does not modify this list or the other.
            The returned list is the same class as the receiver.
            Assumes the receiving type has an initializer that takes a `capacity as int`.
            """

        def get(flexibleIndex as int) as T
            require
                .count > 0
                (flexibleIndex >= 0 and flexibleIndex < .count) _
                    or (flexibleIndex < 0 and flexibleIndex >= -.count)
        
        def get(flexibleIndex as int, default as T) as T
            ensure
                .count == 0 implies result == default
                (flexibleIndex > .count or flexibleIndex < -.count) _
                    implies result == default
    
        def last as T
            """
            Returns the last element in the list.
            """
            require .count > 0
    
        def numbered as KeyValuePair<of int, T>*
            """
            Returns a stream of pairs of (index, value).
            Can be used like so:
                for i, value in someList.numbered
                    ...
            """
    
        def numberedDown as KeyValuePair<of int, T>*
            """
            Returns a stream of pairs of (index, value) in reverse order from
            the end of the list down.
            
            Can be used like so:
                for i, value in someList.numberedDown
                    ...
            """

        def random as T
            require .count > 0
            return .random(CobraCore.random)

        def random(r as Random) as T
            require .count > 0
            return this[r.next % .count]

        def removeLast
            require .count > 0
            ensure .count == old .count - 1
            .removeAt(.count-1)
        
        def reversed as List<of T>
            ensure
                result is not this
                result.count == .count
    
        def sorted as List<of T>
            ensure
                result is not this
                result.count == .count
        
        def sorted(comparison as Comparison<of T>) as List<of T>
            ensure
                result is not this
                result.count == .count
            
        def sorted(comparer as Comparer<of T>) as List<of T>
            ensure
                result is not this
                result.count == .count
    
        def swap(i as int, j as int)
            """
            Swaps the elements at the given indexes which can be negative to index from the end of the
            list towards the front (-1 is last element, -2 is second to last, etc.).
            """
            require
                i >= -.count and i < .count
                j >= -.count and j < .count
            ensure
                old this[i] == this[j]
                old this[j] == this[i]
                .count == old.count


    extend Stack<of T>

        def clone as Stack<of T>
            ensure
                result is not this
                result.count == .count
                result.typeOf is .typeOf


    extend IDictionary<of TKey, TValue>

        def clone as IDictionary<of TKey, TValue>  # CC: as same
            """
            Returns a new dictionary with the contents of this dictionary.
            Does not clone the contents themselves.
            This is sometimes known as a "shallow copy".
            """
            ensure
                result is not this
                result.count == .count
                result.typeOf is .typeOf

        def get(key as TKey, default as TValue) as TValue
            """
            Returns the value for the given key, or returns the default if the key is not found.
            """
            ensure not .containsKey(key) implies result == default

You can see the full source for these in the source Cobra.Lang directory.

Specifically

See also: PrimitiveTypeMembers, TypeExtensions, LibraryTopics