From: Tom Sawyer Date: 2002-07-15T10:01:28+09:00 Subject: RE: hey! where's #count? (clearing up degeneration) --=-VLrgdu8TQESNJv2Gm8kB Content-Type: text/plain Content-Transfer-Encoding: 7bit so i tried my hand at including count in Enumberable and "normalizing" String and Hash accordingly. take a look at the attached script to see how the current design is a tad odd, versus how these changes effect it. module Enumerable def count(c) self.select { |i| i == c }.length end end class String alias contains count remove_method :count def each each_byte { |c| yield c.chr } end end class Hash remove_method :include? # each is synonomous with each_value, not each_pair alias each each_value # include key shoud be the primary method, has_key the alias but... alias include_key? has_key? # ditto for value alias include_value? has_value? def include_pair? # detect_pair ...?... now we start getting bushwacked :-) end end for String, #conatins will do what #count use to. i also redefined #each to be each character, so then one would need to use use #each_line for what #each used to mean (we could have just redefined what record seperator '' means, but would require $/ take regexps to compensate for what '' used to mean) Hash is seriously inept at being normalized, as #include? should be synonomous with has_value? and #count? should count on values. thus #each needs to mean #each_value. trying to "normalize" Hash leads to filling it with all sorts of methods: #detect_key, #detect_pair, #count_key, #count_pair...etc." This all stems from the fact that Hash isn't really Enumberable. #each_with_index, for instance, is meaningless, since a Hash is unordered, and the components of a Hash, the pairs (x=>y) aren't true objects in themselves. for starters, anaylizing this in depth has led me to beleive that Enumberable itself really is a intersection of two different types of mixins. On the one hand everthing realated to #each partakes of their own mixin called, say, Iterable. then the methods involving <=> (and == actually) would be left in Enumerable which also mixes-in Iterable. thus hash is Iterable, but it is not Enumberable. this distinction would help clear up "degeneration", and the seperation could be useful elsewhere, perhaps in Set, for instance. but then there is the consideratin that x=>y, the Hash pairs may best symbolize real objects, x=>y being the literal form. actually it is odd that they don't with ruby being 100% OO. is there any other such thing in ruby? having the hash pairs as objects would actually make ordered hashes pretty easy to make: [ x1=>y1, x2=>y2, ... ] they are just arrays of these pairs, and in fact may be capable of replacing Hash altogether.(?) class HashPair attr_reader :index, :value def initialize @index @value end # ... whatever methods make sense end HashPair may not be the best name. what do you call them? but you get the idea. i'm very interested on hearing your thoughts on this. ~transami On Sun, 2002-07-14 at 09:34, Christoph wrote: > > > > -----Original Message----- > > From: Philipp Meier [mailto:meier@meisterbohne.de] > > Sent: Sunday, July 14, 2002 5:20 PM > > To: ruby-talk ML > > Subject: Re: hey! where's #count? > > > > On Sun, Jul 14, 2002 at 11:41:55PM +0900, Christoph wrote: > > > > > The problem is that some Enumerable classes like the Hash class or > > > a Set class (see for example rough/lib/set.rb - OT I am not sure why > > > this implementation doesn't include Comparable) don't know the > > > about the idea of multiple occurrences consequently you would > > > optimize #count to > > > > > > def count(c) > > > each {|e| return 1 if e == c } > > > return 0 > > > end > > > > > > which is sort of an indication (to me) that #count doesn't really > into > > > Enumerable ... > > > > Considering Enumerables like Set or Hash as a degenerated Enumerable I > > find #count makes sense in Enumberable. Hash or Set can easily provide > > optimized versions of #count. It like find for a sorted list which can > > True - I guess my point was that the Hash/Set degeneration is so > common, that it is hard to speak(write) about "degeneration". > > > /Christoph > > -- ~transami _(")_ dobee dobee do... \v/ ^ ^ --=-VLrgdu8TQESNJv2Gm8kB Content-Disposition: attachment; filename=t2.rb Content-Transfer-Encoding: quoted-printable Content-Type: text/x-ruby; name=t2.rb; charset=ANSI_X3.4-1968 string =3D "12343" array =3D [1,2,3,4,3] hash =3D {'a'=3D>1,'b'=3D>2,'c'=3D>3,'d'=3D>4,'e'=3D>3} puts puts "As is:" puts puts "String: #{string.inspect}" puts "string.select { |c| c } -> #{string.select { |c| c }.inspect}" puts "string.include?('3') -> #{string.include?('3')}" puts "string.count('3') -> #{string.count('3')}" puts puts "Array: #{array.inspect}" puts "array.select { |c| c } -> #{array.select { |c| c }.inspect}" puts "array.include?(3) -> #{array.include?(3)}" puts "* count n/a" #puts "array.count(3) -> #{array.count(3)}" puts puts "Hash: #{hash.inspect}" puts "hash.select { |c| c } -> #{hash.select { |c| c }.inspect}" puts "hash.include?(3) -> #{hash.include?(3)}" puts "hash.include?('c') -> #{hash.include?('c')}" puts "hash.include?(['c',3]) -> #{hash.include?(['c',3])}" puts "* count n/a" #puts "hash.count(3) -> #{hash.count(3)}" #puts "hash.count('c') -> #{hash.count('c')}" #puts "hash.count(['c',3]) -> #{hash.count(['c',3])}" module Enumerable def count(c) self.select { |i| i =3D=3D c }.length end end class String alias contains count remove_method :count def each each_byte { |c| yield c.chr } end end class Hash remove_method :include? # each is synonomous with each_value, not each_pair alias each each_value # include key shoud be the primary method, has_key the alias but... alias include_key? has_key? # ditto for value alias include_value? has_value? end puts puts puts "Adjusted:" puts puts "String: #{string.inspect}" puts "string.select { |c| c } -> #{string.select { |c| c }.inspect}" puts "string.include?('3') -> #{string.include?('3')}" puts "string.count('3') -> #{string.count('3')}" puts puts "Array: #{array.inspect}" puts "array.select { |c| c } -> #{array.select { |c| c }.inspect}" puts "array.include?(3) -> #{array.include?(3)}" puts "array.count(3) -> #{array.count(3)}" puts puts "Hash: #{hash.inspect}" puts "hash.select { |c| c } -> #{hash.select { |c| c }.inspect}" puts "hash.include?(3) -> #{hash.include?(3)}" puts "hash.count(3) -> #{hash.count(3)}" puts --=-VLrgdu8TQESNJv2Gm8kB--