Giter VIP home page Giter VIP logo

act's Introduction

Act

Library for dynamic functional programming and more.

Enter this command and go to the documentation:

pip install act4

Overview

from typing import Optional, Callable

from act import *


def division_between(a: int, b: int) -> int | bad[str]:
    if a == 0 or b == 0:
        return bad("division by zero")

    return a / b


WithNumber = type(number=N)

WithMultiplication = type(multiplication=M)
WithDivision = type(division=D)

Result = WithMultiplication[N] & WithDivision[N]


@fbind_by(... |then>> on(None, bad("something is missing")))
@do(maybe, optionally, for_input=optionally)
def func(do: Do, a: WithNumber[Optional[int]], b: WithNumber[Optional[int]]) -> Result[int]:
    maybe, optionally = do

    first_number = optionally.same(a.number)
    second_number = optionally.same(b.number)
    
    division = maybe(division_between)(first_number, second_number)
    multiplication = first_number * second_number

    return Result(multiplication, division)


# As a result, `func` has this type.
func: Callable[
    [Optional[WithNumber[Optional[int]]], Optional[WithNumber[Optional[int]]]],
    Result[int] | bad[str],
]

assert func(WithNumber(16), WithNumber(2)) == obj(multiplication=32, division=8)
assert func(WithNumber(16), WithNumber(0)) == bad("division by zero")
assert func(WithNumber(16), WithNumber(None)) == bad("something is missing")
assert func(WithNumber(16), None) == bad("something is missing")


class RawResult:
    def __init__(self, multiplication: int, division: int) -> None:
        self.multiplication = multiplication
        self.division = division


assert (
    Result(32, 8)
    == RawResult(32, 8)
    == WithMultiplication(32) & WithDivision(8)
    == obj(multiplication=32, division=8)
)

act's People

Contributors

emptybutton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

act's Issues

All boolean operations for types

Currently, the library has available operations | (or) and & (and) on types, but to correspond to all binary operations there is not enough ! (not) operation.

Need to add the ability for not_ to be executed in the isinstance function with the corresponding functionality in this form:

assert not isinstance(not_(int), int())
assert isinstance(not_(int), str())

assert not isinstance(not_[int], int())
assert isinstance(not_[int], str())

Add annotating decorator

Need to implement the following functionality for centralized annotating:

...

Send = Callable[str, bool]
User = type(name=str, age=int)


@Is[Send]
def send_via_email(message: str) -> bool:
    ...


@Is[User]
@obj
class chingzhenmen:
    name = "Chingzhenmen"
    age = 24

    def do_chingzhenmen(self) -> ...:
        ...


# To avoid:
# send_via_email: Send
# chingzhenmen: User

Add modules

Need to implement a constructor with similar behavior:

@module
class something:
    a = 5

    def add(a):
        return a * 2

    @val
    class sub_value:
        def add(module, b):
            return module.a + b

        class sub_sub_value:
            def add(module, b):
                 return module.a + b

    @obj
    class sub_object:
        c = 2

        def add(module, self, b):
            return (module.a + b) * self.c

    @module
    class sub_module:
        b = 4

        def add(module, b):
            return module.a + b

        @val
        class sub_sub_value:
            def add(module, sub_module, c):
                return module.a + sub_module.b + c

Make `struct` native

struct "sees" only annotated attributes, but to set default values annotation is not needed, but to set them in struct they must still be annotated.

Need to implement this behavior for struct:

@struct
class Something:
    a: int
    b = 8


assert Something.b == 8
assert Something(int()).b == 8

Optimize pipeline creation

Each new use of |then>> creates a separate instance of ActionChain, which must each time combine all functions in a pipeline into a separate function and since it does this using bind, then only the number of calls to bind is n**2 / 2, where n is the number of atomic functions in a pipeline.

Head-on solution: initialize _main_action only if a pipeline (ActionChain) is called and add a special initialization mode for ActionChain when it is created via |then>> operator (_ActionChainInfix).

Add neutral results

Need to return a neutral result whenever possible instead of throwing errors:

assert tuple(indexed(str(), 0, 2)) == tuple()

Clear cursor namespace

Generating getting a name that is in the cursor namespace, you need to add underscore to their name, which is not convenient and users are not required to know the names of the cursor namespace.

Head-on solution: refactor everything protected from _ActionCursor into separate functions and variables or make it all private (the first is preferable).

Simplify `contexted`

contexted's context declarization functionality is better served by be, but be implements context declarization by calling contexted.

Head-on solution: move the context declarization code from contexted to be, leaving contexted only the contextual form declarization.

Optimize cursor creation

At each cursor generation step, a new cursor and a large number of subcursors are created as intermediate stages of generation using suboptimal logic, while access to subcursors is isolated, and using intermediate cursors of one generation for another is bad practice.

Head-on solution: implement creation of new cursors only at a start of generation using a flag attribute and rewrite functions for creating intermediate generation cursors and subcursors from immutable to mutable with a return of not a new one but a modified current one.

Extensibility for `do`

do is a decorator for using monads in the Python function syntax, but historically it has been implemented by transaction code and it lies in their module.

You need to move do to monads.py and refactor it to use plugins, so that you can expand do for custom solutions and add solutions for already implemented monads, which also needs to be done.

Remove signature generation

Every time almost any "generation" function in the library is called, it also tries to generate a signature for its "created function". Referring to signatures and constructing them again takes a lot of time, and often code responsible for the signatures can be as much or even larger than a “generator's” payload code, but clean signatures are only needed for partially because only it reads signatures and uses them in its "generation".

Act prioritizes partial application over currying, so partially (commonly called curry in other libraries) is intended to decorate regular functions rather than "generated" functions. In this case, generating signatures does not make sense as it simply opens up the possibility of bad practices from the point of view of this library.

Head-on solution: remove signature generation and add the ability to independently set the number of obligatory parameters in partially (if the created function still needs a polymorphic interface, but it is also decorated with "generating" functions for its needs).

Hash values

val does not hash values correctly. Need to fix it:

# Now
assert not val() in {val(), val(a=4)}
assert not val() in {1, 2, 3}

# Need
assert val() in {val(), val(a=4)}
assert not val() in {1, 2, 3}

Optimize cursor parameter initialization

After each step of cursor generation, it constantly validates and sorts its parameters, which is very slow, while entering parameters into a cursor is completely isolated.

Head-on solution: add an initialization mode with a different cursor, optimizing sorting and checking in one cycle.

Optimize execution of cursor generated functions

After cursors have already generated their desired functions, they are still waiting for generating, which is a bad practice and not optimal.

Head-on solution: prevent cursors from generating after calling their generated function and add a cache

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.