Idea: Compose class should be iterable
ZeroBomb opened this issue · 2 comments
It would be really nice to be able to iterate all the funcs in compose, without having to combine the first
and funcs
properties. It would let you immediately use Compose objects as iterables in the itertoolz functions.
For an example, consider the simple logging strategy outlined in my gist here:
https://gist.github.com/ZeroBomb/8ac470b1d4b02c11f2873c5d4e0512a1
As written, I need to define this somewhat extraneous function
def get_funcs(composition):
return (composition.first,)+composition.funcs
in order to map over those functions and re-compose:
@curry
def interleave_map(func, items):
# [1,2,3] -> [func(1), 1, func(2), 2, func(3), 3]
return interleave([map(func, items), items])
# define a debug function that interleaves logging funcs inbetween each func in an existing composition
debug = compose_left(get_funcs, interleave_map(passthru_log), star(compose_left))
if the Compose class were iterable, I could completely eliminate the get_funcs function, and comfortably feed the compose object directly into interleave:
def debug(composition):
return compose_left(*interleave_map(passthru_log, composition))
My compose
exposes all composed callables as the .functions
attribute, in case that helps.
Some other observations on iterable compositions:
Idempotence
There is a sense in which compose is idempotent:
compose(*compose(f1, f2, f3)) == compose(f1, f2, f3)
Is that good? I don't know, but it seems profound.
Trivial mapping over compositions
It is now basically trivial to update the functions inside compositions you've already made
def log(func):
def inner(*args, **kwargs):
print(f"callin' {func.__name__}")
return func(*args, **kwargs)
return inner
compose(*map(log, preexisting_composition))
Suggests future direction for combining compositions
It seems pretty straightforward to propose some kind of helper function to make this a little more straightforward
compose(*composition2, *composition1)
but it's not that bad as-is.