hyrious / chain

write python with chain dsl
MIT License
0 stars 0 forks source link

A small thought #2

Closed asukaminato0721 closed 3 years ago

asukaminato0721 commented 3 years ago

in mathematica, user can do this:

expr // f // g // h

which equals h[g[f[expr]]]

also, can write as this:

expr // f[ parms,  #, parms] & // g[ parms , #, parms] &

equals

g[  ... ,  f[... ,  expr , ...]   , ...]

looks more general purpose.

I was trying to do sth like

mma(expr).map(lambda x:x , slot).other_func...

mma and slot are key words.

asukaminato0721 commented 3 years ago
import builtins
from typing import Any, Callable

class wl:
    """usage:
    >>> list(wl([1, 2, 3]).map(lambda x: x + 2, slot + [1, 2]))
    [3, 4, 5, 3, 4]
    """

    def __init__(self, expr: Any):
        self.expr = expr

    def __repr__(self):
        return repr(self.expr)

    def __iter__(self):
        return iter(self.expr)

    def __getattr__(self, name):
        f_head: Callable = getattr(builtins, name)
        slot.x = self.expr

        def warpped(f, arg):
            return wl(f_head(f, arg))

        return warpped

class Slot:
    def __init__(self, x="x"):
        self.x = x

    def __add__(self, other):
        return eval(f"{self.x} + {other}")

    def __pow__(self, other):
        return eval(f"{self.x} ** {other}")

    def __call__(self, *args: Any, **kwds: Any) -> Any:
        return eval(self.x)

slot = Slot()

if __name__ == "__main__":
    from doctest import testmod

    testmod()
    print(list(wl([1, 2, 3]).map(lambda x: x ** 2, slot + [1, 2])))

fin

hyrious commented 3 years ago

@wuyudi added slot, is this what you want?

chain([1, 2, 3]).map(it ** 2, slot + [1, 2]).to_list().print() #=> [1, 4, 9, 1, 4]
asukaminato0721 commented 3 years ago

I make a small change,

https://github.com/hyrious/chain/blob/be071710b14e0baeb7f6ebcee6f4ac1cd24ff7af/chain.py#L27-L28

Turn to

            name.startswith("to_")
            and callable(value := eval(name[3:]))
            or callable(value := eval(name))

then can do this:

if __name__ == "__main__":
    from operator import add

    chain([1, 2, 3]).add([4, 54, 6], slot).set(slot).print()  # set and to_set does the same thing.

but I don't know why this get an error

if __name__ == "__main__":
    from operator import add

    chain([1, 2, 3]) # I know add \ can fix this
    .add([4, 54, 6], slot)
    .set(slot)
    .print()

https://stackoverflow.com/a/4768979/13040423

And this is what has been mentioned:

if __name__ == "__main__":
    from operator import add
    from functools import reduce

    chain([1, 2, 3]).add([4, 54, 6], slot).reduce(add, slot).print()

it can support reduce with ease.


in the end, why slot?

https://reference.wolfram.com/language/ref/Slot.html?q=Slot

asukaminato0721 commented 3 years ago

More fun:

This method can do:

    def slot(self, *args, **kwargs):
        return chain(self.obj(*args, **kwargs))
chain(add).slot(1, 2).print()

in mma:

Plus // #[1, 2] &
asukaminato0721 commented 3 years ago

For fun :P

https://github.com/wuyudi/Mathematica-style-pipe-Python/blob/master/pipe.py