On Tue, Jan 12, 2016 at 6:26 PM Franklin? Lee <leewangzhong+python@gmail.com> wrote:
On Sun, Jan 10, 2016 at 3:27 AM, Bill Winslow <bunslow@gmail.com> wrote:
> Sorry for the late reply everyone.
>
> I think relying on closures, while a solution, is messy. I'd still much
> prefer a way to tell lru_cache to merely ignore certain arguments.

Wait, why is it messy? The function is created inside the outer
function, and never gets released to the outside. I think it's
cleaner, because it's encapsulating the recursive part, the memo, and
the cached work. Besides, `lru_cache` is implemented using a closure,
and your solution of passing a key function might be used with a
closure on a nested function.

If you're solving dynamic programming puzzles, an outer/inner pairing
of non-recursive/recursive represents the fact that your memoization
can't be reused for different instances of the same problem. (See, for
example, Edit Distance
(https://web.stanford.edu/class/cs124/lec/med.pdf), in which your
recursive parameters are indices into your non-recursive parameters.)


> I've further considered my original proposal, and rather than naming it
> "arg_filter", I realized that builtins like sorted(), min(), max(), etc all
> already have the exact same thing -- a "key" argument which transforms the
> elements to the user's purpose. (In the sorted/min/max case, it's called on
> the elements of the argument rather than the argument itself, but it's still
> the same concept.) So basically, my original proposal with renaming from
> arg_filter to key, is tantamount to extending the same functionality from
> sorted/min/max to lru_cache as well.

I like this conceptually, because the `key` parameter sort of lets you
customize the cache dict (or whatever). You can use, for example,
`str.lower` (though not directly).

Note that the key parameter in those other functions allows you to
call the key function only once per element, which is impossible for
this.

Should it be possible to specify a tuple for `key` to transform each
arg separately? In your case, you might pass in `(None, lambda x: 0)`
to specify that the first parameter shouldn't be transformed, and the
second parameter should be considered constant. But that's very
confusing: should `None` mean "ignore", or "don't transform" (like
`filter`)? Or we can use `False` for "ignore", perhaps.

I think his intention was to mimic the ``key`` argument of sorted, which expects a function that takes 1 and only 1 positional argument.

Perhaps it's best to see the exact use case and a few other examples, to get a better idea for the specifics, before implementing this feature?

On Sun, Jan 10, 2016 at 2:03 PM, Michael Selik <mike@selik.org> wrote:
> Shouldn't the key function be called with ``key(*args, **kwargs)``?

Does `lru_cache` know how to deal with passing regular args as kwargs? 

Now that you mention it, I realized it treats the two differently.
``def foo(x): pass`` would store ``foo(42)`` and ``foo(x=42)`` as different entries in the cache.