parmap
parmap copied to clipboard
Iterable as a second argument
It is possible to easily achieve something like:
def f(x, y):
r = 0
for i in range(100000000000):
r += i
return r
parmap.map(f, x=1, y=range(100))
?
Yes, just use a helper function:
def g(y, x):
return f(x, y)
parmap.map(g, range(100), x=1)
There is also https://docs.python.org/3.6/library/functools.html#functools.partial
If you have a suggestion for an alternative API, feel free to suggest it.
I was thinking that maybe map can assign the iterable to y because the value of x was given explicitly. Similarly, starmap could assign iterables to the subsequent arguments that were not explicitly provided in **kwargs.
On 16 March 2018 at 19:46, Sergio Oller [email protected] wrote:
Yes, just use a helper function:
def g(y, x): return f(x, y)
parmap.map(g, range(100), x=1)
There is also https://docs.python.org/3.6/library/functools.html# functools.partial
If you have a suggestion for an alternative API, feel free to suggest it.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/zeehio/parmap/issues/15#issuecomment-373809314, or mute the thread https://github.com/notifications/unsubscribe-auth/AEuSHZ9syigC7E8FPBc3IJI6w4TxzP5Wks5tfAhtgaJpZM4St3tA .
I have some concerns with that approach:
There is a use case where an extra argument is an iterable:
def times2(xlimits, x):
xmin = xlimits[0]
xmax = xlimits[1]
if x < xmin:
x = xmin
if x > xmax:
x = xmax
return 2*x
parmap.map(times2, xlimits = [0, 5], x = range(10))
It would be harder (impossible) in this case for parmap to guess that the iterable argument is the second one.
It is then possible to modify times2
so as if xlimits
is a single number it assumes it is a single boundary (xmax) and, if it is a two element list then it follows the previous definition:
def times2b(xlimits, x):
if isinstance(xlimits, (int, float)):
xmin = -float('Inf')
xmax = xlimits
else:
xmin = xlimits[0]
xmax = xlimits[1]
if x < xmin:
x = xmin
if x > xmax:
x = xmax
return 2*x
parmap.map(times2, xlimits = 5, x = range(10))
parmap.map(times2, xlimits = [0, 5], x = range(10))
Here with your API proposal, the first call would work as expected, the second one would not do what we wanted. It could surprise parmap users.
For an interactive use (such as in a notebook) the approach you suggest is good, in most cases it will do what we want and we will like it.
However, parmap users may start to use that syntax in their python packages, and their users may use those packages in surprising ways that can lead to parmap iterating in the wrong argument.
https://en.m.wikipedia.org/wiki/Principle_of_least_astonishment
Besides, by reading at your first example I could also think that you wanted to compute f(x=1, y=range(100))
and that you meant:
parmap.map(f, x=[1], y=range(100))
. Currently we can catch the error while with your API we would get a surprising result.
What would you think of an API like:
parmap.map(f, x=1, y=range(100), pm_iter="y")
?
My idea was that
parmap.map(times2, xlimits = [0, 5], x = range(10))
should simply call times2 with the given arguments but
parmap.map(times2, range(10), xlimits = [0, 5])
parmap.map(times2, iterable=range(10), xlimits = [0, 5])
could call times2 with different values of x. Do you find it surprising?
At the same time, I like
parmap.map(f, x=1, y=range(100), pm_iter="y")
It is nicely explicit.