Reputation: 735
I would like to be able to do, for example:
pmap = persistent_map(function, iterable(args))
foo = map(bar, pmap)
baz = map(bar, pmap) # right-hand side intentionally identical to that of the previous line.
The interpreter would know to reset pmap
before using it to construct baz
.
I know that I could store the result of pmap
as a tuple
, list
, or other structure (which is what I have done in my present application), but I don't want to have do that because of the possibilities of 1) huge storage requirements (also consider copies) and 2) different results on reevalation, as when iterable
is produced from a dynamic file.
If the equivalent of persistent_map
exists, what is the corresponding built-in feature or standard library feature? Alternatively, is there a third-party (hopefully reliable and readily available) persistent_map
equivalent? If only extant option is third-party, how might you create persistent_map
using only built-in and, possibly, standard library features?
In response to @MartijnPieters comment, "that's what generators are for", are you saying that one solution would be something like
def persistent_map(function, iterable):
from functools import partial
return partial(map, function, iterable)
foo = map(bar, pmap())
baz = map(bar, pmap())
# A toy example:
pmap = persistent_map(hex, range(3))
foo = map(len , pmap())
baz = map(hash, pmap())
print(*zip(pmap(), foo, baz))
('0x0', 3, 982571147) ('0x1', 3, 982571146) ('0x2', 3, 982571145)
In response to @kmiya ("Bit too late...") and also, now that I think I understand better what @MartijnPieters meant by "that's what generators are for," I would do it this way:
class PersistentMap:
def __init__(self, func, generator):
self.func = func
self.generator = generator
def __iter__(self):
return map(
self.func,
# THIS IS HOW "The interpreter [knows] to reset:"
self.generator()
)
# AN EXAMPLE GENERATOR.
# NOTE THAT STORING "ALL" THE GENERATED VALUES IS IMPOSSIBLE.
def tictoc():
k = 0
while True:
yield k
k = 1 - k
pmap = PersistentMap(hex, tictoc)
bar = map(len, pmap)
baz = map(hash, pmap)
limiter = range(3)
print(*zip(pmap, bar, baz, limiter))
# ('0x0', 3, 9079185981436209546, 0) ('0x1', 3, -8706547739535565546, 1) ('0x0', 3, 9079185981436209546, 2)
print(*zip(pmap, bar, baz, limiter))
# ('0x0', 3, 9079185981436209546, 0) ('0x1', 3, -8706547739535565546, 1) ('0x0', 3, 9079185981436209546, 2)
Upvotes: 1
Views: 510
Reputation: 31
Bit too late, but I think this would be what the OP imagined to have:
class PersistentMap:
def __init__(self, func, iterable):
self.func = func
self.iterable = iterable
def __iter__(self):
return map(self.func, self.iterable)
foo = PersistentMap(hex, range(3))
bar = map(len, foo)
baz = map(hash, foo)
print(*zip(foo, bar, baz))
# ('0x0', 3, -1640763679766387179) ('0x1', 3, -4170177621824264673) ('0x2', 3, 4695884286851555319)
Upvotes: 2