adamantium icon indicating copy to clipboard operation
adamantium copied to clipboard

Cache built-in query methods of immutable object

Open dkubb opened this issue 12 years ago • 12 comments

This branch memoizes the #hash, #to_s and #inspect methods automatically since they are based on the instance state, and cannot change since the instance state is immutable.

[Fix #9]

dkubb avatar Dec 16 '13 08:12 dkubb

@dkubb I think the intent of this change is okay. But I fear we run into ordering issues with equalizer, concord, anima includes. Can we guard against overriding the memoized #hash, #inspect etc?

mbj avatar Dec 16 '13 10:12 mbj

@mbj I wonder if a method_added hook could be used to warn when a memoized method is being overridden in the same class/module it's defined within? Or it could just re-memoize the method.

One downside to warning is if someone defines their own #hash (or #inspect or #to_s) then they'll get tons of warnings which are meaningless.

dkubb avatar Dec 16 '13 17:12 dkubb

@mbj, @dkubb - now that these gems are being combined in interesting ways seems to be a good time to talk about the ordering and needed methods. Ideally they don't need to be done in any order, right? The ordering gets increasingly complicated as we add more and more gems. It's ironic to be worried about overridden methods given some recent rants about ActiveSupport. I wish I had more to add to actually help. Mostly just echoing the concern and offering to help if I can.

elskwid avatar Dec 16 '13 18:12 elskwid

@dkubb IMHO: I'd be okay to issue a warning. If someone dislikes these warnings he can define their own #hash and friends, than import Adamantium or dont use this library. I'd generally favor doing what fulfills my needs, and than focus on imaginary users. Avoiding doing decisions and creating to much options just limits effectiveness of the lib and development speed: "Library authors should provide solutions, not more options.".

My typical code looks like this:

class Foo
  include Adamantium, Concord.new(:bar, :baz)
end

Module#include applies includes in reverse order, concord uses equalizer to set up #hash and friends. So adamantium with auto memoization of #hash and friends would fit my style perfectly.

mbj avatar Dec 16 '13 18:12 mbj

@mbj what about using method_added to memoize #to_s, #to_hash and #inspect when they are added?

dkubb avatar Dec 16 '13 21:12 dkubb

@dkubb Yeah. This will allow equalizer and similar libs to work without ANY knowlege about adamantium +1. I think this is the way to go.

mbj avatar Dec 16 '13 21:12 mbj

@dkubb Maybe you should NOT memoize #hash and friends by default. Only if a method missing was detected!

mbj avatar Dec 16 '13 21:12 mbj

@mbj method_missing won't kick in because they'll inherit those methods from Object.

dkubb avatar Dec 16 '13 21:12 dkubb

@dkubb I meant method_added. Sorry obviousely NOT method missing ;)

mbj avatar Dec 16 '13 21:12 mbj

This PR needs to be rebased; bundle install fails because of old gem dependencies.

orend avatar May 19 '14 15:05 orend

@orend I rebased this against master so it should be usable.

dkubb avatar Aug 11 '14 07:08 dkubb

My latest commit adds a #method_added hook that will memoize a method when it is added.

However, it loses the ability to memoize the built-in #to_s and #inspect methods. I couldn't make them both work because you can't re-memoize a method twice in the same class.

What I think may need to happen is a change in memoize itself where you can memoize a specific method only once, but if the method is overridden you can memoize it again. Once this change is done, then the built-in #to_s and #inspect methods can be automatically memoized again.

dkubb avatar Aug 11 '14 08:08 dkubb