EntilZha / PyFunctional

Python library for creating data pipelines with chain functional programming
http://pyfunctional.pedro.ai
MIT License
2.41k stars 132 forks source link

Tuple argument unpacking functionality #163

Open Kache opened 3 years ago

Kache commented 3 years ago

http://www.python.org/dev/peps/pep-3113/ removed tuple param unpacking so in Python 3:

(
    seq((1, 2), (3, 4))
    .map(lambda a, b: a + b)  # TypeError: <lambda>() missing 1 required positional argument: 'b'
)

more background:

https://stackoverflow.com/questions/21892989/what-is-the-good-python3-equivalent-for-auto-tuple-unpacking-in-lambda https://stackoverflow.com/questions/11328312/python-lambda-does-not-accept-tuple-argument

Seeing as how unpacking can be implemented explicitly using more functions:

import functools

def unpack(f):
    @functools.wraps(f)
    def unpacked(args):
        return f(*args)
    return unpacked

(
    seq((1, 2), (3, 4))
    .map(unpack(lambda a, b: a + b))
)  # => [3, 7]

How about building that functionality as an option, directly into all the seq() methods? e.g.:

(
    seq((1, 2), (3, 4))
    .map(unpack=lambda a, b: a + b)
)

Also, a more powerful nested unpacking variation by (ab)using comprehensions:

(
    seq((1, (2, 3)), (3, (4, 5)))
    .map(lambda t: next(a + b + c for a, (b, c) in (t,)))
)

but not sure that one can be smoothly worked in like unpack

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

EntilZha commented 3 years ago

In the first example, would smap make things work correctly? If so, map has already been special cased. There had been a request before to add that functionality to all relevant functions, but I wasn't convinced it was worth expanding the API so much. I'd be open to picking a targeted subset though, likely those that have exactly 1 positional argument that is a function (e.g., map, flat_map).

Doing keyword argument for this seems hard, it would mean needing to make the positional argument optional and then checking if it is empty or not versus unpack.

I could definitely see including unpack as a utility function, ergonomically speaking using that versus a keyword isn't that different. I'd be curious to see how long the list of functions would be that have 1 positional argument, it is a function, and the function can take multiple arguments.

giuseppe16180 commented 2 years ago

I would love a feature like this

bmsan commented 2 years ago

@EntilZha I like what you mentioned about having unpacking for all the functions. What would you think about an automated way of deciding to unpack

Scenario1: check the number of mandatory parameters(without default values) required by the provided function. If they are more than one unpack. The above scenario is a case where the code would have crashed, so we are not causing anyharm.

Scenario2: The tricky part would the following: if you have a function that takes 2 arguments, the second being optional, you don't know if the caller actually wants you to unpack or not. (the second argument could be just a flag that changes the way the processing is performed). So the above is a case where you wouldn't want to unpack because we don't know the effects.

If scenario1 sounds ok, anybody in scenario2 which would want unpacking would just have to call their function from a lambda and pyfunctional would see it as needing unpacking.