// title: tagger // author: vividsnow // description: // tag system sketch // code: ( // create tagger ~t = { var lib = Dictionary(); { |w,k,op='|'| if(w.isNil.not and: w.isMemberOf(Association).not, { [k,w] do: {|t| [t].flatten do: {|i| lib.includesKey(i).not.if({ lib[i] = Set() })} }; k.isNil.not.if({ [k].flatten do: {|i| [w].flatten do: {|j| lib[i] = [lib[i],j].reduce(op); lib[j] = [lib[j],i].reduce(op); }} }) }); w.isNil.if({lib}, { var op = '&'; w.isMemberOf(Association).if({ op = w.value; w = w.key }); [w].flatten.collect(lib[_]).reduce(op) }) } }.(); ); // usage // add ops Ndef(\kick) !? ~t.(\kikin,_); // add tag for ndef Ndef(\kick) !? ~t.([\bassy,\perc],_); // add tags for ndef ~t.([\bassy,\perc], Ndef(\kick)); // same ~t.(Ndef(\kick), [\bassy,\perc]); // same Ndef(\bass) !? ~t.([\bassy,\perc,\fav],_); // same [Ndef(\kick), Ndef(\bass)] !? ~t.([\some,\thing],_); // many-to-many ~t.([Ndef(\kick), Ndef(\bass)], [\some,\thing]); // same // get ops ~t.(Ndef(\bass)); // get tags by ndef ~t.(\perc); // get ndefs by tag ~t.([\perc,\fav]); // get ndefs by tag list - matching all ~t.([\perc,\fav]->'&'); // same ~t.([\perc,\fav]->'|'); // get ndefs by tag list - matching any ~t.([\perc,\fav]->'-'); // get ndefs by tag list - matching first but not second ~t.([Ndef(\kick),Ndef(\bass)]); // get tags by ndefs - matching all ~t.([Ndef(\kick),Ndef(\bass)]->'|'); // get tags by ndefs - matching any ~t.() // get underlying structure // remove ops Ndef(\kick) !? ~t.(\kikin,_,'-'); // remove tag Ndef(\kick) !? ~t.([\some,\thing],_,'-'); // remove tags // nb: Ndef can be substituted with any other class, // but collisions may occur in case of usage of same class // both for tags and tagged objects (e.g. Symbol to Symbol)