Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

functional if, ==, in, *, assert #472

Closed
uriva opened this issue Oct 16, 2019 · 8 comments
Closed

functional if, ==, in, *, assert #472

uriva opened this issue Oct 16, 2019 · 8 comments

Comments

@uriva
Copy link

uriva commented Oct 16, 2019

I find myself needing these extras to replace python operators that don't work well within pipelines. If maintainers would like I can submit a pull request.

def curried_ternary(condition, f_true, f_false):
    def inner(*args, **kwargs):
        return (
            f_true(*args, **kwargs)
            if condition(*args, **kwargs)
            else f_false(*args, **kwargs)
        )

    return inner

def star(function: Callable) -> Callable:
    return lambda x: function(*x)


@toolz.curry
def _assert_f_output_on_inp(f, inp):
    assert f(inp)


def assert_that(f):
    return curried.do(_assert_f_output_on_inp(f))


@toolz.curry
def contains(container, element):
    return element in container

@toolz.curry
def equals(x, y):
    return x == y
@uriva uriva changed the title functional if, == and in, *, assert functional if, ==, in, *, assert Oct 16, 2019
@groutr
Copy link
Contributor

groutr commented Oct 17, 2019

Your contains and equals are already available in toolz.curried.operator

EDIT: The curried_ternary is interesting. Typically, I've encountered that logic inside the functions that make up the pipeline (ie the stage decides which result to return based on its input).
Can you give a use case for star and assert_that?

@uriva
Copy link
Author

uriva commented Oct 19, 2019

Had no idea. Can they be documented somehow?

assert_that gives you an ability to assert within a toolz.pipe, sort of like inline sanity without adding noise to the implementation. e.g.

toolz.pipe(7, increment, assert_that(greater(7)))

star is important because many functions are not unary, and the pipeline can't handle that, so you end up making the signatures less readable by nesting within tuples.

e.g.

def addition(a: int, b: int) -> int:
  return a + b

toolz.pipe((7,8), star(addition))

without star I would have to write the less readble

def addition(input: Tuple[int, int]) -> int:
  return input[0] + input[1]

@groutr
Copy link
Contributor

groutr commented Oct 22, 2019

@uriva you're right, they aren't really visible. It looks like toolz curries most of the operator module.

@eriknw thoughts on star and assert_that?

@mentalisttraceur
Copy link

By the way star is the same idea as the unpack suggested in #486. Someone suggested calling it starapply, and today I thought of starcall and that seems decent too.

Since I'm already here: I suggest renaming curried_ternary to curried_if_else - "ternary" just means "has three operands/parameters". Ditto conditional to predicate - more idiomatic. Also the function body reads easier if you use the statement instead of the operator:

-        return (
-            f_true(*args, **kwargs)
-            if condition(*args, **kwargs)
-            else f_false(*args, **kwargs)
-        )
+        if condition(*args, **kwargs):
+            return f_true(*args, **kwargs)
+        else:
+            return f_false(*args, **kwargs)

@uriva
Copy link
Author

uriva commented May 12, 2022

@mentalisttraceur this thread is 3 years old, we've since implemented these and many others in gamla. with support for async functions as well.

@uriva uriva closed this as completed May 12, 2022
@mentalisttraceur
Copy link

mentalisttraceur commented May 12, 2022

this thread is 3 years old

Yeah I know how to read timestamps. If it stopped being relevant and you didn't want replies anymore, you had three years to communicate that by closing this issue and/or making that comment.

@mentalisttraceur
Copy link

gamla looks pretty cool at a glance. I appreciate someone else handling async functions too! I did that in compose with acompose, and I was recently thinking of doing a more dynamic thing where the composition returns either an awaitable or not based on whether or not any of the composed functions returns an awaitable - it looks like you did something similar, nice.

@uriva
Copy link
Author

uriva commented May 19, 2022

@mentalisttraceur yes. so glad you liked it!
there's a lot of cool stuff we did there, and some cool stuff ahead (e.g. type safety)
the library is used in production for a couple of years now and matured nicely.
we welcome more users and contributors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants