; From: Dat Thuc Nguyen ; Date: Wed, 7 Apr 1999 15:33:30 +0000 ; URL: http://www.smalltickle.com ; ; CONTAINER IS A KEY CONCEPT IN OBJECT-ORIENTED PROGRAMMING. ; SMALLTALK, C++, etc. HAVE STANDARD LIBRARIES OF CONTAINERS. ; THE FOLLOWING SCRIPT DEFINES THE CLASS BAG IN C-KERMIT/KERMIT 95, ; BAG OFFERS A RICH USAGE INTERFACE: ; ; bag bag_name ; create a new object identified as bag_name. ; ; bag_name.put key value ; deposit into the object bag_name the element ; identified by 'key' that has the content 'value'. ; Both key and value can be alpha, numeric, alpha-numeric. ; ; bag_name.get key ; query the element identified by 'key'. ; ; bag_name.size ; query the number of the elements in the bag_name. ; ; bag_name.pairs ; query all the pairs key => value in the bag_name. ; ; bag_name.values ; query all the values in the bag_name. ; ; bag_name.keys ; query all the keys in the bag_name. ; ; bag_name.reset ; remove all the elements in the bag_name. ; ; bag_name.every_value dothis ; apply dothis to every value of bag_name. ; ; bag_name.every_key dothis ; apply dothis to every key of bag_name. ; ; bag_name.drop key ; remove element identified by key from bag_name. ; ; bag_name.destroy ; remove the bag_name itself. ;************************************************************************ ;* SERVICE IMPLEMENTATION TO ALL OBJECTS OF CLASS BAG * ;* TO REDUCE THE CODE DUPLICATION FOR EACH OBJECT * ;************************************************************************ define bag_service.reset { _assign \%1_size 0 _assign \%1_dictionary \x02 } define bag_service.put { local \%f \%i \%l \%m \%n \%v assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%f \findex(\%m\%2\%n, \m(\%1_dictionary)) xif = \%f 0 { ; key not yet used? _assign \%1_dictionary \m(\%1_dictionary)\%2\%n\%3\%m assign \%z \m(\%1_size) ; get previous size increment \%z ; update size _assign \%1_size \%z ; save size } else { assign \%i \feval(\%f + \flength(\%m\%2\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) assign \%l \feval(\%f - \%i) assign \%v \fsubstring(\m(\%1_dictionary),\%i,\%l) _assign \%1_dictionary - \freplace(\m(\%1_dictionary),\%n\%v\%m,\%n\%3\%m) } } define bag_service.get { local \%f \%i \%v \%l \%m \%n assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%f \findex(\%m\%2\%n,\m(\%1_dictionary)) xif = \%f 0 { echo \%2 IS UNKNOWN KEY IN THIS OBJECT } else { assign \%i \feval(\%f + \flength(\%m\%2\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) assign \%l \feval(\%f - \%i) assign \%v \fsubstring(\m(\%1_dictionary),\%i,\%l) echo \%2 => \%v } } define bag_service.pairs { local \%f \%i \%k \%l \%m \%n \%v assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%i \feval(1 + \flength(\%m)) ; start dictionary while < \%i \flength(\m(\%1_dictionary)) { assign \%f \findex(\%n, \m(\%1_dictionary), \%i) ; key pos assign \%l \feval(\%f - \%i) ; key length assign \%k \fsubstring(\m(\%1_dictionary), \%i, \%l) ; key assign \%i \feval(\%f + \flength(\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) ; value pos assign \%l \feval(\%f - \%i) ; value length assign \%v \fsubstring(\m(\%1_dictionary), \%i, \%l) ; value echo \%k => \%v assign \%i \feval(\%f + \flength(\%m)) ; next key pos } } define bag_service.keys { local \%f \%i \%k \%l \%m \%n assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%i \feval(1 + \flength(\%m)) ; start dictionary while < \%i \flength(\m(\%1_dictionary)) { assign \%f \findex(\%n, \m(\%1_dictionary), \%i) ; key pos assign \%l \feval(\%f - \%i) ; key length assign \%k \fsubstring(\m(\%1_dictionary), \%i, \%l) ; key assign \%i \feval(\%f + \flength(\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) ; value pos assign \%l \feval(\%f - \%i) ; value length echo \%k assign \%i \feval(\%f + \flength(\%m)) ; next key pos } } define bag_service.values { local \%f \%i \%k \%l \%m \%n \%v assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%i \feval(1 + \flength(\%m)) ; start dictionary while < \%i \flength(\m(\%1_dictionary)) { assign \%f \findex(\%n, \m(\%1_dictionary), \%i) ; key pos assign \%l \feval(\%f - \%i) ; key length assign \%i \feval(\%f + \flength(\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) ; value pos assign \%l \feval(\%f - \%i) ; value length assign \%v \fsubstring(\m(\%1_dictionary), \%i, \%l) ; value echo \%v assign \%i \feval(\%f + \flength(\%m)) ; next key pos } } define bag_service.every_value { local \%f \%i \%k \%l \%m \%n \%v assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%i \feval(1 + \flength(\%m)) ; start dictionary while < \%i \flength(\m(\%1_dictionary)) { assign \%f \findex(\%n, \m(\%1_dictionary), \%i) ; key pos assign \%l \feval(\%f - \%i) ; key length assign \%i \feval(\%f + \flength(\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) ; value pos assign \%l \feval(\%f - \%i) ; value length assign \%v \fsubstring(\m(\%1_dictionary), \%i, \%l) ; value \%2 \%v ; apply \%2 on val assign \%i \feval(\%f + \flength(\%m)) ; next key pos } } define bag_service.every_key { local \%f \%i \%k \%l \%m \%n \%v assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%i \feval(1 + \flength(\%m)) ; start dictionary while < \%i \flength(\m(\%1_dictionary)) { assign \%f \findex(\%n, \m(\%1_dictionary), \%i) ; key pos assign \%l \feval(\%f - \%i) ; key length assign \%k \fsubstring(\m(\%1_dictionary), \%i, \%l) ; key assign \%i \feval(\%f + \flength(\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) ; value pos assign \%l \feval(\%f - \%i) ; value length \%2 \%k ; apply \%2 on key assign \%i \feval(\%f + \flength(\%m)) ; next key pos } } define bag_service.drop { local \%f \%i \%k \%l \%m \%n \%v \%z assign \%m \x02 ; STX assign \%n \x03 ; ETX assign \%f \findex(\%m\%2\%n, \m(\%1_dictionary)) ; get key xif = \%f 0 { ; not yet used? echo \%2 IS UNKNOWN KEY IN THIS OBJECT } else { assign \%i \feval(\%f + \flength(\%m\%2\%n)) assign \%f \findex(\%m, \m(\%1_dictionary), \%i) assign \%l \feval(\%f - \%i) assign \%v \fsubstring(\m(\%1_dictionary),\%i,\%l) _assign \%1_dictionary - \freplace(\m(\%1_dictionary),\%m\%2\%n\%v) assign \%z \m(\%1_size) ; previous size increment \%z -1 ; update size _assign \%1_size \%z ; save size } } define bag_service.destroy { \%1.reset _define \%1_size _define \%1_dictionary _define \%1.size _define \%1.put _define \%1.get _define \%1.pairs _define \%1.reset _define \%1.keys _define \%1.values _define \%1.every_value _define \%1.every_key _define \%1.drop _define \%1.destroy } define bag { _assign \%1_dictionary \x02 ; STX _assign \%1_size 0 _define \%1.put { if NOT define \%1 end 1 ... missing 1.param if NOT define \%2 end 1 ... missing 2.param bag_service.put \fbreak(\v(macro),.) \%1 \%2 } _define \%1.get { bag_service.get \fbreak(\v(macro),.) \%1 } _define \%1.pairs { bag_service.pairs \fbreak(\v(macro),.) } _define \%1.size { local \%s assign \%s \fbreak(\v(macro),.) echo \m(\%s_size) return \m(\%s_size) } _define \%1.reset { bag_service.reset \fbreak(\v(macro),.) } _define \%1.keys { bag_service.keys \fbreak(\v(macro),.) } _define \%1.values { bag_service.values \fbreak(\v(macro),.) } _define \%1.every_value { bag_service.every_value \fbreak(\v(macro),.) \%1 } _define \%1.every_key { bag_service.every_key \fbreak(\v(macro),.) \%1 } _define \%1.drop { bag_service.drop \fbreak(\v(macro),.) \%1 } _define \%1.destroy { bag_service.destroy \fbreak(\v(macro),.) } } ;************************************************************************ ;* USAGE EXAMPLE * ;************************************************************************ bag abc ; Buy a new bag abc abc.put a 1 ; Put the key a with the value 1 in the bag abc abc.put b 2 ; Put the key b with the value 2 in the bag abc abc.put c 3 ; Put the key c with the value 3 in the bag abc abc.pairs ; Show me all the pairs key => value abc.keys ; Show me all the keys abc.values ; Show me all the value define sum 0 define sum_it { assign sum \feval(\%1 + \m(sum)) ; sum ::= \%1 + \m(sum) <-- C-Kermit 7.0 } abc.every_value sum_it ; Add all the value in the bag abc echo \m(sum) ; Show the sum abc.put name Jordan ; Put the key name with a value Jordan in the bag abc abc.pairs ; Show me all the pairs key => value abc.put 1999 Year ; Put the key 1999 with the value Year in the bag abc abc.pairs ; Show me all the pairs key => value abc.put book Buch ; English - German abc.put Buch book ; German - English abc.drop name ; Jordan retires abc.pairs ; Show me all the pairs key => value abc.reset ; empty the bag abc for \%i 1 50 1 { abc.put a\%i b\%i } abc.pairs ; Show me all the pairs key => value abc.destroy ; Throw the bag abc into the gabbage end