Partial vs function literal when memoize

2019-06-22 14:13发布

问题:

This is giving me a bit of brain thump:

user> (repeatedly 10 #((memoize rand-int) 10))
(7 0 4 8 1 2 2 1 6 9)
user> (repeatedly 10 (partial (memoize rand-int) 10))
(8 8 8 8 8 8 8 8 8 8)

I would like to know if the reason for this is because the function literal (first version) is called/evaluated every time, thus the memoize is "recreated" (re-memorized) each time, therefore not really having any true meaningful "memorization" at all, while the second one with partial is actually returning a fixed function that is evaluated just once, where the same value of memoize is thus used every time (sort of like a closure though I don't think this qualifies as a true "closure")

Am I thinking correctly?

回答1:

Yes, memoize doesn't modify its argument in any way, so

#((memoize rand-int) 10)

recreates the memoized function on each call.

(fn [] ((memoize rand-int) 10))

is equivalent.

To call a memoized function from another function, you need to put it in a Var or a closed-over local:

(repeatedly 10 (let [r (memoize rand-int)] #(r 10)))
;= (2 2 2 2 2 2 2 2 2 2)

In the partial example, the function returned by (memoize rand-int) is passed as an argument to the function partial, which then returns a closure which closes over the return of (memoize rand-int). So, this is very close to the example above (except the closure returned by partial uses apply to call the memoized function).