On Sun, Dec 9, 2012 at 7:19 PM, Intransition <[email protected]> wrote:
> The note `TODO: Improve Hash#rekey code!!!` has been in my docs for too
> long. I could use other's insights and thought others might enjoy the
> challenge. So here's the code:
I think the problem is in the API. That's what makes it too complex.
There are too many cases of specific handling and options (see below):
> require 'facets/na'
>
> class Hash
>
> # Rekey a hash:
> #
> # rekey()
> # rekey(from_key => to_key, ...)
> # rekey{|from_key| to_key}
> # rekey{|from_key, value| to_key}
> #
> # If a key map is given, then the first key is changed to the second
> key.
> #
> # foo = { :a=>1, :b=>2 }
> # foo.rekey(:a=>'a') #=> { 'a'=>1, :b=>2 }
> # foo.rekey(:b=>:x) #=> { :a =>1, :x=>2 }
> # foo.rekey('foo'=>'bar') #=> { :a =>1, :b=>2 }
> #
> # If a block is given, converts all keys in the Hash accroding to the
> # given block procedure. If the block returns +NA+ for a given key,
> # then that key will be left intact.
1. Unnecessary option: if the key is supposed to stay intact the block
should just return the original key.
> #
> # foo = { :name=>'Gavin', :wife=>:Lisa }
> # foo.rekey{ |k| k.to_s } #=> { "name"=>"Gavin", "wife"=>:Lisa }
> # foo #=> { :name =>"Gavin", :wife=>:Lisa }
> #
> # If no key map or block is given, then all keys are converted
> # to Symbols.
2. Why that default? In my mind this is too much implicit logic.
Also this can be easily achieved with
hash.rekey(&:to_sym)
> #
> # Note that if both a +key_map+ and a block are given, the +key_map+ is
> # applied first then the block.
3. I would change that to EITHER block OR map argument, but not both.
> Not the use of `facets/na`. That is defined as:
>
> class << NA = ArgumentError.new
> def inspect ; 'N/A' ; end
> def method_missing(*); self; end
> end
>
> But it is really nothing more than a dummy object used to mean Not
> Applicable. So in the case of #rekey, if the block returns NA then the key
> goes unchanged. Thinking about it again now, it's probably unnecessary, but
> I had wanted a way to say "leave it alone" while also making sure that `nil`
> could still be used as a key (even if that's rare). Feel free to remove the
> NA business, but if you do please explain why you think its not needed.
If one needs a special key one can use a Symbol for that as
efficiently as nil. nil is the value return if something is absent
and I believe it does not make for a good key in a Hash.
> Best solution will get their name put in front of CREDITs for the next
> release of Facets.
:-)
class Hash
def rekey(mapping = nil, &convert)
c = convert || mapping
dup.tap do |h| # preserve type and defaults
h.clear
each_pair {|k, v| h[c[k] || k] = v}
end
end
end
Kind regards
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
-- You received this message because you are subscribed to the Google Groups
ruby-talk-google group. To post to this group, send email to
[email protected]. To unsubscribe from this group, send email
to [email protected]. For more options, visit this
group at https://groups.google.com/d/forum/ruby-talk-google?hl=en