i2mint/creek

Fluid interface ideas

Opened this issue · 0 comments

The code below shows an idea of fluid interface.

We're showing it as "explicit code" here, but it's obvious that there's a lot of pattern repetition here and we should implement a plugin architecture to be able to "register" new stacking methods:

class Stacker:
    def __init__(self):
        self.pipe_stack = list()
            
    def append(self, func):
        self.pipe_stack.append(func)
        return self
    
    def extend(self, *funcs):
        self.pipe_stack.extend(*func)
        return self
        
    def map(self, func):
        self.pipe_stack.append(partial(map, func))
        return self
        
    def filter(self, func):
        self.pipe_stack.append(partial(filter, func))
        return self
    
    def list(self):
        self.pipe_stack.append(list),
        return self
    
    def join(self, sep):
        self.pipe_stack.append(sep.join)
        return self
        
    def __call__(self, *args, **kwargs):
        return Pipe(*self.pipe_stack)(*args, **kwargs)
    
    @property
    def __signature__(self):
       # TODO: Just example here. Need to implement more context-specific robust signature here.
        from inspect import signature
        first_element_of_stack = next(iter(self.pipe_stack), None)
        if first_element_of_stack:
            return signature(self.first_element_of_stack)
        

Here is an example of use.

print_keys_ending_in_dol = (
    Stacker()
        .map(itemgetter(0))
        .filter(lambda x: x.endswith('dol'))
        .map(lambda x: f"'{x}'")
        .join(', ')
        .append(print)
)

print_keys_ending_in_dol(pkg_and_deps)

Note: Should find a way to percolate the 'dol' to be a parameter of the stacker callable.
We can use the same method as meshed.DAG or lined.ParametrizedLine does to achieve the same.

The above is basically equivalent to doing this:

it = map(itemgetter(0), pkg_and_deps)
it = filter(lambda x: x.endswith('dol'), it)
it = map(lambda x: f"'{x}'", it)
print(*it, sep=', ')

or otherwise put:

from operator import itemgetter
from i2 import Pipe
from functools import partial

g = Pipe(
    partial(map, itemgetter(0)),
    partial(filter, lambda x: x.endswith('dol')),
    partial(map, lambda x: f"'{x}'"),
)
it = map(itemgetter(0), pkg_and_deps)
it = filter(lambda x: x.endswith('dol'), it)
print(*g(pkg_and_deps), sep=', ')

To see this example in it's context, see appendix of this wiki

┆Issue is synchronized with this Asana task by Unito