⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 container.jam

📁 C++的一个好库。。。现在很流行
💻 JAM
字号:
# (C) Copyright Rene Rivera, 2002.
#
# See accompanying license for terms and conditions of use.
#

# Various container classes.

import "class" : * ;

# Base for container objects. This lets us construct recursive structures.
# That is containers with containers in them, specifically so we can tell
# literal values from node values.
#
class node 
{
    rule __init__ (
      value ? # Optional value to set node to initially.
    )
    {
        self.value = $(value) ;
    }
        
    # Set the value of this node, passing nothing will clear it.
    #
    rule set ( value * )
    {
        self.value = $(value) ;
    }
    
    # Get the value of this node.
    #
    rule get ( )
    {
        return $(self.value) ;
    }
}


# A simple vector. Interface mimics the C++ std::vector and std::list,
# with the exception that indices are one (1) based to follow Jam standard.
#
# TODO: Possibly add assertion checks.
#
class vector : node 
{
    import numbers : range ;
    import utility ;
    import sequence ;
        
    rule __init__ (
      values * # Initial contents of vector.
    )
    {
        node.__init__ ;
        self.value = $(values) ;
    }    
    
    # Get the value of the first element.
    #
    rule front ( )
    {
        return $(self.value[1]) ;
    }
    
    # Get the value of the last element.
    #
    rule back ( )
    {
        return $(self.value[-1]) ;
    }
    
    # Get the value of the element at the given index, one based.
    # Access to elements of recursive structures is supported directly.
    # Specifying additional index values recursively accesses the elements as
    # containers. For example: [ $(v).at 1 : 2 ] would retrieve the second element
    # of our first element. This assuming the first element is a container.
    #
    rule at (
        index # The element index, one based.
        : * # Additional indices to access recursively.
        )
    {
        local r = $(self.value[$(index)]) ;
        if $(2)
        {
            r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
        }
        return $(r) ;
    }
    
    # Get the value contained in the given element. This has the same
    # functionality and interface as "at" but in addition gets the value
    # of the referenced element, assuming it's a "node".
    #
    rule get-at (
        index # The element index, one based.
        : * # Additional indices to access recursively.
        )
    {
        local r = $(self.value[$(index)]) ;
        if $(2)
        {
            r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
        }
        return [ $(r).get ] ;
    }
    
    # Insert the given value into the front of the vector pushing the
    # rest of the elements back.
    #
    rule push-front (
        value # Value to become first element.
        )
    {
        self.value = $(value) $(self.value) ;
    }
    
    # Remove the front element from the vector. Does not return the value.
    # No effect if vector is empty.
    #
    rule pop-front ( )
    {
        self.value = $(self.value[2-]) ;
    }
    
    # Add the given value at the end of the vector.
    #
    rule push-back (
        value # Value to become back element.
        )
    {
        self.value += $(value) ;
    }
    
    # Remove the back element from the vector. Does not return the value.
    # No effect if vector is empty.
    #
    rule pop-back ( )
    {
        self.value = $(self.value[1--2]) ;
    }
    
    # Insert the given value at the given index, one based. The values
    # at and to the right of the of the index are push back to make room
    # for the new value.
    #
    rule insert (
        index # The index to insert at, one based.
        : value # The value to insert.
        )
    {
        local left = $(self.value[1-$(index)]) ;
        left = $(left[1--2]) ;
        local right = $(self.value[$(index)-]) ;
        self.value = $(left) $(value) $(right) ;
    }
    
    # Remove one or more elements from the vector. The range is inclusive,
    # and not specifying an end is equivalent to the [start,start] range.
    #
    rule erase (
        start # Index of first element ro remove.
        end ? # Optional, index of last element to remove.
        )
    {
        end ?= $(start) ;
        local left = $(self.value[1-$(start)]) ;
        left = $(left[1--2]) ;
        local right = $(self.value[$(end)-]) ;
        right = $(right[2-]) ;
        self.value = $(left) $(right) ;
    }
    
    # Remove all elements from the vector.
    #
    rule clear ( )
    {
        self.value = ;
    }
    
    # The number of elements in the vector.
    #
    rule size ( )
    {
        return [ sequence.length $(self.value) ] ;
    }
    
    # Returns "true" if there are NO elements in the vector, empty
    # otherwise.
    #
    rule empty ( )
    {
        if ! $(self.value)
        {
            return true ;
        }
    }

    # Returns the list of all valid indices for this vector.
    rule indices ( )
    {
        if ! [ empty ] 
        {
            local size = [ size ] ;
            return [ range 1 : $(size) ] $(size) ;
        }      
    }

    # Returns the textual representation of content.
    rule str ( )
    {
        return "[" [ sequence.transform utility.str : $(self.value) ] "]" ;
    }

    # Sorts the vector inplace, calling 'utility.less' for
    # comparisons.
    # NOTE: this rule is unused at the moment.
    rule sort ( )
    {
        self.value = 
            [ sequence.insertion-sort $(self.value) : utility.less ] ;
    }

    # Returns true if content is equal to the content of other vector.
    # Uses 'utility.equal' for comparison.
    rule equal ( another )
    {        
        local mismatch ;
        if [ size ] = [ $(another).size ]
        {
            for local i in [ indices ]
            {
                if ! [ utility.equal [ at $(i) ] [ $(another).at $(i) ] ]
                {
                    mismatch = true ;
                }
            }
        } 
        else
        {
            mismatch = true ;
        }
                        
        if ! $(mismatch) 
        {
            return true ;
        }
    }
}

local rule __test__ ( )
{
    import assert ;
    import "class" : new ;
    
    local l = [ new vector ] ;
    assert.result 0 : $(l).size ;
    assert.result : $(l).indices ;
    assert.result "[" "]" : $(l).str ;
    $(l).push-back b ;
    $(l).push-front a ;
    assert.result 1 2 : $(l).indices ;
    assert.result "[" a b "]" : $(l).str ;
    assert.result a : $(l).front ;
    assert.result b : $(l).back ;
    $(l).insert 2 : d ;
    $(l).insert 2 : c ;
    $(l).insert 4 : f ;
    $(l).insert 4 : e ;
    $(l).pop-back ;
    assert.result 5 : $(l).size ;
    assert.result d : $(l).at 3 ;
    $(l).pop-front ;
    assert.result c : $(l).front ;
    assert.false $(l).empty ;
    $(l).erase 3 4 ;
    assert.result 2 : $(l).size ;
    
    local l2 = [ new vector q w e r t y ] ;
    assert.result 6 : $(l2).size ;
    $(l).push-back $(l2) ;
    assert.result 3 : $(l).size ;
    local l2-alias = [ $(l).back ] ;
    assert.result e : $(l2-alias).at 3 ;
    $(l).clear ;
    assert.true $(l).empty ;
    assert.false $(l2-alias).empty ;
    $(l2).pop-back ;
    assert.result t : $(l2-alias).back ;
    
    local l3 = [ new vector ] ;
    $(l3).push-back [ new vector 1 2 3 4 5 ] ;
    $(l3).push-back [ new vector a b c ] ;
    assert.result "[" "[" 1 2 3 4 5 "]" "[" a b c "]" "]" : $(l3).str ;
    $(l3).push-back [ new vector [ new vector x y z ] [ new vector 7 8 9 ] ] ;
    assert.result 1 : $(l3).at 1 : 1 ;
    assert.result b : $(l3).at 2 : 2 ;
    assert.result a b c : $(l3).get-at 2 ;
    assert.result 7 8 9 : $(l3).get-at 3 : 2 ;

    local l4 = [ new vector 4 3 6 ] ;
    $(l4).sort ;
    assert.result 3 4 6 : $(l4).get ;

    assert.false $(l4).equal $(l3) ;
    local l5 = [ new vector 3 4 6 ] ;
    assert.true $(l4).equal $(l5) ;
    # Check that vectors of different sizes are considered non-equal
    $(l5).pop-back ;    
    assert.false $(l4).equal $(l5) ;
    local l6 = [ new vector [ new vector 1 2 3 ] ] ;
    assert.true $(l6).equal [ new vector [ new vector 1 2 3 ] ] ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -