pytoolz / toolz

A functional standard library for Python.
http://toolz.readthedocs.org/
Other
4.57k stars 258 forks source link

`thread_as` function ?? #540

Open gkspranger opened 1 year ago

gkspranger commented 1 year ago

is there any way to achieve a "thread as" experience like there is in Clojure ??

https://clojuredocs.org/clojure.core/as-%3E

my goal is to be able to use the result from the previous evaluation, anywhere in the current evaluation .. i get that the "variable" declaration (v) could conflict with future args, but if i am allowed to "name" my variable and it is unique enough -- i could reasonably assume my positional arguments would be safe from conflicts ..

for example, i would hope to be able to do something like this ::

v = f"{uuid.uuid4()}some_variable_name_that_wont_collide_with_future_derived_vals"
def add(x, y): return x + y
def pow(x, y): return x**y

thread_as(
    1, v,
    (add, 4, v),
    (pow, v, 2),
)
# 25

if there is another way to achieve it -- i would love to hear it ..

thanks for the help !!

gkspranger commented 1 year ago

just in case there is no current way to do this, i tried hacking at it and came up with the solution below (WARNING: non-expert-pythoner) .. so it does seem possible -- but again, if there is an existing way to accomplish this, i would like to know about it ..

thanks again

from functools import partial, reduce
import uuid

v = f"{uuid.uuid4()}myspecialvar"
def add(x, y): return x + y
def pow(x, y): return x**y

def thread_as(val, v, *forms):
    def to_as_variable(val, arg):
        return val if arg == v else arg

    def evalform_as(val, form):
        if isinstance(form, tuple):
            func, args = form[0], form[1:]
            return func(*map(partial(to_as_variable, val), args))
    return reduce(evalform_as, forms, val)

print(
    thread_as(
        1, v,
        (add, 4, v),
        (pow, v, 2),
    )
)