returns icon indicating copy to clipboard operation
returns copied to clipboard

Question: Tuple returns as arguments

Open kyprifog opened this issue 5 years ago • 8 comments

How would you do something like the following, ie unpack tuple as arguments for next function within flow

@safe
def method_b(arg_a: str, arg_b: int) -> int:
     return len(arg_a) + arg_b

@safe
def method_a() -> Tuple[str, int]:
   return ("abc", 3)

a = flow(
   method_a(),
   bind(method_b)
)

a.unwrap()
>> 6

kyprifog avatar Nov 30 '20 03:11 kyprifog

You would have to use a lambda function: bind(lambda my_tuple: method_b(*my_tuple))

sobolevn avatar Nov 30 '20 10:11 sobolevn

I tried that, but for some reason any time I use bind(lambda a: in dry python suddenly in any context I get "unknown first argument for bind function."

I assumed that bind(lambda was no longer supported

kyprifog avatar Nov 30 '20 13:11 kyprifog

Yes, looks like lambda cannot be infered here. I would recommend to create an intermediate function in this case:

from returns.result import Result, safe
from returns.pointfree import bind
from returns.pipeline import flow
from typing import Tuple

@safe
def method_a() -> Tuple[str, int]:
   return ("abc", 3)

@safe
def method_b(arg_a: str, arg_b: int) -> int:
     return len(arg_a) + arg_b

def _method_b_args(t: Tuple[str, int]) -> Result[int, Exception]:
    return method_b(*t)

a = flow(
    method_a(),
    bind(_method_b_args),
)

reveal_type(a)

sobolevn avatar Nov 30 '20 16:11 sobolevn

Yeah this is what I settled for, but it would be nice if tuples could be inferred (or have an option) to be function arguments by default? Maybe thats a little overreaching though.

kyprifog avatar Nov 30 '20 16:11 kyprifog

I will investigate! Cannot promise, though 😞

sobolevn avatar Nov 30 '20 16:11 sobolevn

Sounds good, let me know, I may come back and revisit if I get a break, I have a couple things in this library that I want to try to push along now that I'm using it more widely.

kyprifog avatar Nov 30 '20 17:11 kyprifog

@sobolevn What about create a helper function?

from returns.functions import unpack_args
from returns.pointfree import bind

flow(
    function_a(),
    bind(unpack_args(function_b))
)

unpack_args could work with list, tuple and dict. Maybe we'll just need some magic in our mypy plugin!

thepabloaguilar avatar Dec 02 '20 21:12 thepabloaguilar

I thought about this, this is probbably a good middle ground / short term solution. Although, tbh, I was having so many issues with flow i've stopped using it for now, just went back to a long multiline string

kyprifog avatar Dec 02 '20 23:12 kyprifog