# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and # distribute this software is granted provided this copyright notice appears in # all copies. This software is provided "as is" without express or implied # warranty, and with no claim as to its suitability for any purpose. import assert ; # Note that algorithms in this module execute largely in the caller's # module namespace, so that local rules can be used as function # objects. Also note that most predicates can be multi-element # lists. In that case, all but the first element are prepended to the # first argument which is passed to the rule named by the first # element. # Return the elements e of $(sequence) for which [ $(predicate) e ] is # has a non-null value. rule filter ( predicate + : sequence * ) { # trailing underscores hopefully prevent collisions with module # locals in the caller local result__ ; module [ CALLER_MODULE ] { for local e in $(sequence) { if [ $(predicate) $(e) ] { result__ += $(e) ; } } } return $(result__) ; } rule less ( a b ) { if $(a) < $(b) { return true ; } } # insertion-sort s using the BinaryPredicate ordered. rule insertion-sort ( s * : ordered * ) { ordered ?= sequence.less ; local result__ = $(s[1]) ; module [ CALLER_MODULE ] { for local x in $(s[2-]) { local head tail ; tail = $(result__) ; while $(tail) && [ $(ordered) $(tail[1]) $(x) ] { head += $(tail[1]) ; tail = $(tail[2-]) ; } result__ = $(head) $(x) $(tail) ; } } return $(result__) ; } # join the elements of s into one long string. If joint is supplied, it is used as a separator. rule join ( s * : joint ? ) { local result ; joint ?= "" ; for local x in $(s) { result = $(result)$(joint)$(x) ; result ?= $(x) ; } return $(result) ; } local rule __test__ ( ) { # use a unique module so we can test the use of local rules. module sequence.__test__ { local rule is-even ( n ) { if $(n) in 0 2 4 6 8 { return true ; } } assert.result 4 6 4 2 8 : sequence.filter is-even : 1 4 6 3 4 7 2 3 8 ; # test that argument binding works local rule is-equal-test ( x y ) { if $(x) = $(y) { return true ; } } assert.result 3 3 3 : sequence.filter is-equal-test 3 : 1 2 3 4 3 5 3 5 7 ; local rule test-greater ( a b ) { if $(a) > $(b) { return true ; } } assert.result 1 2 3 4 5 6 7 8 9 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 ; assert.result 9 8 7 6 5 4 3 2 1 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 : test-greater ; assert.result foo-bar-baz : sequence.join foo bar baz : - ; assert.result substandard : sequence.join sub stan dard ; } }