matz / zetabits.com (Yukihiro Matsumoto) wrote: > Hi, > > In message "[ruby-talk:5947] Hash.new {block} / Hash#default_proc{,_set}" > on 00/10/31, "Brian F. Feldman" <green / FreeBSD.org> writes: > > |I've done very little testing, but I think I've successfully implemented the > |ability for a Hash to provide a default procedure rather than variable. > | > |The only reasonable way I could think of doing this required on-the-fly > |creation of a hash entry when a lookup fails -- otherwise, this feature is > |nearly useless (does not make anything easier). > | > |Here's the diff, my 3rd time modifying Ruby code itself. Comments? > > Three points: > > * currently each internal structure sizes are made strictly less > than 5 pointer size for space efficiency. Hm, I see, with RVALUE. I learned something new now! Fixed... > * your on-the-fly entry creation idea sound reasonable; but I think > we need to discuss it before merging it. Well, I've changed my little API a bit... default_proc is a flag to set and the behavior is deterministic based upon this. > * we need to inspect cost/benefit between this patch and Hash#fetch > which already takes a block to give a value for non existing > entry. Perhaps. It's just the idiomatic differences, really; you can currently do (bear with the fact that this is an example that isn't too useful :) hash[var] ||= 0; hash[var] += 1 hash[var] = hash.fetch(var, 0) + 1 Neither of these is optimal because they are too complicated to be a good idiom. Maybe a "hash.fetch(var, 0) += 1"? That would be impossible... So onto "hash[var] += 1" -- this works for immutable types or non-modifying calls, but suppose I want to do: lines = File.open(x) {|y| y.collect {|n| n.chomp!}} if i_do_not_like_this_one def words_lines(lines) h = Hash.new lines.each_with_index {|l, i| l.split.each {|w| h[w] ||= [] h[w].push(l) } } end else def words_lines(lines) h = Hash.new {[]} # can't do this because Array.new is called only once: # h = Hash.new([]) lines.each_with_index {|l, i| l.split.each {|w| h[w].push(l) } } end end puts words_lines(lines) Which seems "nicer" to you? I Like the second a lot more because it's idiomatic in the way This was an example of the issue brought up earlier (with << instead of push, but...) on the list, but I don't recall which message number it was. > Thank you anyway. Just a proposal, thanks for looking :) -- Brian Fundakowski Feldman \ FreeBSD: The Power to Serve! / green / FreeBSD.org `------------------------------'