Support memoizing methods with block parameters#15
Support memoizing methods with block parameters#15mjcbsn22 wants to merge 1 commit intomakandra:masterfrom
Conversation
2415501 to
af8eb21
Compare
Methods with `&block` parameters previously raised `CannotMemoize`. This change strips the block from the cache key (since blocks cannot be meaningfully hashed) and forwards it to the original method on cache miss. On subsequent calls, the cached return value is used regardless of the block passed. This is the correct behavior when the block is part of the method's internal implementation rather than an external input that changes the return value.
af8eb21 to
52cbfe6
Compare
|
Thanks for the PR @mjcbsn22 .
I didn't understand why it would be safe to ignore a block argument for the cache key. Do you mean scenarios when the block is passed on to another method internally? I really want to prevent memoized methods from silently caching uncacheable invocations, and err on the side of correctness when we cannot know. |
|
@mjcbsn22 During the upgrade to Ruby 3 and adjustments for the new keyword arguments, we discussed support for blocks and rejected it.
|
|
I did wonder whether blocks could make a cache key via their |
They can't. The result of (non-lambda) blocks can depend on the value of surrounding variables, e.g. Here, the call to |
Problem
Calling
memoizeon a method that has a&blockparameter raisesMemoized::CannotMemoize. This prevents memoizing methods that use blocks internally (e.g.transform_values(&:to_s)) even though the block doesn't affect cacheability.Solution
&blockparameters inParametersinstead of raisingThe block is not part of the cache key since blocks cannot be meaningfully hashed. On cache hit, the cached value is returned regardless of the block passed. This is correct when the block is part of the method's internal implementation rather than an external input that changes the return value.
Note: Methods using implicit
yieldwithout an explicit&blockparameter are not affected by this change. Ruby does not report a:blockparameter for such methods, so they remain unchanged.Tests
Added specs covering:
unmemoizeworks correctly for block methodsAll existing tests continue to pass.