On Mon, Dec 10, 2012 at 8:44 PM, Intransition <[email protected]> wrote:
>
>
> On Monday, December 10, 2012 7:22:17 AM UTC-5, Robert Klemme wrote:
>>
>> 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):
>>
>> 1. Unnecessary option: if the key is supposed to stay intact the block
>> should just return the original key.
>
> I agree. Just wanted someone else to confirm. Out it goes!
:-)
>> > #
>> > # 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)
>
>
> I can understand that. I used the default b/c the vast majority of the time
> I was using it to convert to symbols. Rather then have yet another method
> like ActiveSupport's `symbolize_keys` it made more sense to me to just give
> #rekey this as the default.
>
> I can't really take that back now. It's been too long part of the API.
Well, then you mustn't change *anything* which affects observable behavior.
>> > #
>> > # 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.
>
>
> Yea, I thought about that when I added support for the mapping. That was
> actually something that came later that the original block form. At first I
> had thought about making an entirely different method, but then thought that
> was a waste and that it made more sense as part of #rekey. So when I first
> added it I did an "either or", just as you suggest. But then I thought
> "why?" it certainly can handle both even if people will almost never use
> both.
>
> What do you think? Does it really matters enough to change it now? Like I
> said, I doubt anyone has used both, so this is something that could be
> change if it really is worth it.
I would get rid of that behavior. After all, if someone wants do do
Hash lookups as part of conversion they can still do that in the block
without much effort.
I also noticed a slight asymmetry between block and Hash: a block will
return something for every key passed in. But since a Hash is fixed
at the time of method call (modulo default_proc of course) there is
not really a way to handle absent keys ad hoc.
>> > 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.
>
>
> Wouldn't use symbols b/c then you have a special exception. NA was made just
> for such cases. But you probably right that `nil` doesn't make a good hash
> key no matter what. Nonetheless, it doesn't really matter b/c as you said
> above, they can just return the original key.
>
>>
>> > 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
>>
>
> Sweet. Much smaller than mine, that's for damn sure!!!
Yeah, but that's easy when one removes the complexity in behavior.
> Put the default
> :to_sym back in and we could have a deal :-)
Well, that's easy, isn't it?
def rekey(mapping = nil, &convert)
c = convert || mapping || :to_sym.to_proc
> I'm need to test and benchmark it first though.
Have fun!
> Oh, and nice use of polymorphism using #[] for both proc and hash retrieval!
Thank you! :-)
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