"""
Reference Parallel Primitives

These are reference implementations of basic parallel
primitives. These are not actually parallel, but work the same way.
They are good for testing.
"""
from __future__ import print_function, absolute_import

from sage.misc.prandom import shuffle


def parallel_iter(f, inputs):
    """
    Reference parallel iterator implementation.

    INPUT:

    - ``f`` -- a Python function that can be pickled using
      the pickle_function command.

    - ``inputs`` -- a list of pickleable pairs (args, kwds), where
      args is a tuple and kwds is a dictionary.

    OUTPUT:

    - iterator over 2-tuples ``(inputs[i], f(inputs[i]))``, where the
      order may be completely random

    EXAMPLES::

        sage: def f(N,M=10): return N*M
        sage: inputs = [((2,3),{}),  (tuple([]), {'N':3,'M':5}), ((2,),{})]
        sage: set_random_seed(0)
        sage: for a, val in sage.parallel.reference.parallel_iter(f, inputs):
        ....:     print((a, val))
        (((2,), {}), 20)
        (((), {'M': 5, 'N': 3}), 15)
        (((2, 3), {}), 6)
        sage: for a, val in sage.parallel.reference.parallel_iter(f, inputs):
        ....:     print((a, val))
        (((), {'M': 5, 'N': 3}), 15)
        (((2,), {}), 20)
        (((2, 3), {}), 6)
    """
    v = list(inputs)
    shuffle(v)
    for args, kwds in v:
        yield ((args, kwds), f(*args, **kwds))
