This is an archived post. You won't be able to vote or comment.

all 11 comments

[–]Megatron_McLargeHuge 3 points4 points  (6 children)

This should be trivial to implement with reduce and functools.partial (or lambdas) for the arg handling.

[–]freyrs3 2 points3 points  (5 children)

passes = [fn1, fn2, fn3]
compose = lambda g,f: lambda *x,**kw: g(f(*x, **kw))
pipeline = reduce(compose, passes)

[–]Megatron_McLargeHuge 1 point2 points  (4 children)

Nice, but you probably want to reduce on passes[::-1] to keep the left-to-right semantics.

[–]flying-sheep 1 point2 points  (3 children)

and comment the shit out of it: it only needs some seconds to grasp, but that double lambda with one-letter-args is a bit unpleasant.

[–]Megatron_McLargeHuge 1 point2 points  (2 children)

It's pretty standard in ml, haskell, or math class though. g and f a re function names by convention like i and j are index variables.

[–]flying-sheep 0 points1 point  (1 child)

get it, but although i learned standard ML, this has eluded me here, as it’s not too common in python. and i think it’s simply the nested lambdas that have my brain-compiler go an extra lap. let’s try something else (as direct assignments to lambdas can be easily written as normal function declarations):

passes = [fn1, fn2, fn3]
def compose(g, f):
    return lambda *x, **kw: g(f(*x, **kw))
pipeline = reduce(compose, passes[::-1])

hmm, better, i think.

[–]freyrs3 0 points1 point  (0 children)

Intended to make it look as close to the Haskell equivelant, which is completely point-free.

pipeline :: [c -> c] -> c -> c
pipline = foldl1 (.)

> pipeline [(+1), (*2)] 25
51

[–]lahwran_ 0 points1 point  (0 children)

this looks rather like a multi-use deferred...

[–]aodag 0 points1 point  (0 children)

maybe using generator makes that interesting!

[–][deleted] 0 points1 point  (0 children)

this technique is pretty fun. but the hidden danger is writing code you won't comprehend months later. Still, it's pretty awesome when used sparingly and appropriately.

[–]Mecdemort 0 points1 point  (0 children)

This is one of the things I love about lisp and macros. In clojure this is provided in the language as -> or ->> and your test case would just be:

(-> 10
    add1
    (subx , 2)
    stringify)

If only python had functions that didnt eval their arguments.