-- Copyright 1993-1998, by the Cecil Project -- Department of Computer Science and Engineering, University of Washington -- See the LICENSE file for license information. (--DOC The `view_filtered' methods take a predicate function to filter the keys. The `view_subset' function supports the special case where the filtering predicate is that the key is drawn from a particular set. The mutable filtered table implementation doesn't support adding new bindings through the store function, only updating existing bindings. --) -- things may break if viewed table changes its set of legal keys -- and then the view is consulted again. template representation filtered_table[Key,Value,Table <= table[Key,Value]] isa table[Key,Value]; private field table(@:filtered_table[`Key,`Value,`Table]):Table; private field filter(@:filtered_table[`Key,`Value,`Table]):&(Key):bool; private var field cached_length(@:filtered_table[`Key,`Value,`Table]):int := -1; method length(t@:filtered_table[`Key,`Value,`Table]):int { -- this assumes that the number of allowed keys won't change if(t.cached_length = -1, { let var i:int := 0; do_associations(t, &(k:Key,v:Value){ i := i.succ; }); t.cached_length := i; }); t.cached_length } method do_associations(t@:filtered_table[`Key,`Value,`Table], c:&(Key,Value):void):void { do_associations(t.table, &(k:Key,v:Value){ if(eval(t.filter, k), { eval(c, k, v); }); }); } method fetch(t@:filtered_table[`Key,`Value,`Table], key:Key, if_absent:&():Value):Value { if(eval(t.filter, key), { fetch(t.table, key, { error("viewed collection has changed keys") }) }, if_absent) } method collection_name(@:filtered_table[`Key,`Value,`Table]):string { "filtered_table" } -- mutable filtered views. -- can change bindings of keys, but don't support adding new keys to viewee -- table returns an m_table in the child object template representation m_filtered_table[Key,Value,Table <= m_table[Key,Value]] isa filtered_table[Key,Value,Table], m_table[Key,Value]; method store(t@:m_filtered_table[`Key,`Value,`Table], key:Key, value:Value, if_absent:&():void):void { if(eval(t.filter, key), { store(t.table, key, value, { error("viewed collection has changed keys") }) }, if_absent) } -- constructors for filtered views and special cases. method view_filtered(t@:table[`Key,`Value], filter:&(Key):bool) :table[Key,Value] { concrete object isa filtered_table[Key,Value,table[Key,Value]] { table := t, filter := filter } } method view_filtered(t@:m_table[`Key,`Value], filter:&(Key):bool) :m_table[Key,Value] { concrete object isa m_filtered_table[Key,Value,m_table[Key,Value]] { table := t, filter := filter } } -- views of subsets of keys method view_subset(t@:table[`Key <= comparable[Key],`Value], keys@:set[Key]) :table[Key,Value] { view_filtered(t, &&(k:Key){ includes(keys, k) }) } method view_subset(t@:m_table[`Key <= comparable[Key],`Value], keys@:set[Key]) :m_table[Key,Value] { view_filtered(t, &&(k:Key){ includes(keys, k) }) }