forbiddenfp


Nameforbiddenfp JSON
Version 0.9.9.3 PyPI version JSON
download
home_pagehttps://github.com/yx-z/forbiddenfp
SummaryForbidden Functional Programming in Python.
upload_time2024-02-23 23:26:53
maintainer
docs_urlNone
authorDavid
requires_python>=3.7
license
keywords
VCS
bugtrack_url
requirements forbiddenfruit typing_extensions
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # forbiddenfp

## Summary

Functional-Programming (FP) in a forbidden way:

You can turn arbitrary function into postfix notation in favor of function chaining.

And the library provides many useful patches for builtin/itertools functions.

## Install

Compatible with Python 3.7+

```shell
pip install forbiddenfp
```

## Examples

```python
# objects are already patched at import time
import forbiddenfp

"abc".print().len()  # print out "abc", then return 3
"abc".then(lambda s: s * 2).filter(lambda s: s == "b").join()  # "bb"

# A more complex one (examples/word_count.py)
("./lorem_ipsum.txt"
 .with_open(lambda path, f: f.read().also(print(f"Reading {path}")))
 .then(lambda s: s.split(" "))
 .counter()
 .print())

```

See more `./examples`.

## `_unpack`

For every higher-order-function chained, we provide an `_unpack` version as well.
e.g. `[(1, 2), (3, 4)].sum(lambda x: x[0] * x[1])`
can also be called as `[(1, 2), (3, 4)].sum_unpack(lambda x, y: x * y)`

## Why Functional Programming

Separate out control structs (which are functions provided by library) from business logic (which are lambda functions
supplied to fill the control structs).

So we can have a clearer scope, and separate concerns, when we want to change on either side of things.

- `if ...` and `if ... else ...` are modeled by Maybe/Either monads.
- `while ...` and `for ... in ...` are generator/iterators. Additionally, stop-early behavior is `takewhile` of the
  sequence.

Philosophically, think more in `def transform(old_state) -> new_state`, rather than `state = modify(state)`.

## What About Auto-completion?

This library is almost an embedded Domain Specific Language (DSL) in Python.

It is understandable that users aren't familiar with what is available without auto-completion features in IDEs.

So we leverage the stub file to provide type hints for the builtin `object` type, which IntelliJ/PyCharm/VsCode all support.

![img_1.png](img_1.png)

In order to find where to stub, open your IDE and Python project/file, type `object` to get a class, CTRL/CMD + Click and use
"Find Definition" feature to get to the stub file of your IDE plugin.

Then copy/paste `src/forbiddenfp/__init__.py` under `class object` stub.

Note that for IntelliJ/Pycharm, once you CTRL + Click on `object`, you would need to click on the little icon below
to get to the *actual* stub file. Append content there.

![img.png](img.png)

## Warning

This library patches builtin `object` (and hence ALL classes),
with hacks around CPython API (provided by [forbiddenfruit](https://github.com/clarete/forbiddenfruit)),

so consider this NSFW (Not Safe For Work).

## Known Issues

`None` doesn't work well with chained keyword arguments.

```python
import forbiddenfp

None.apply(print)  # works
None.apply(func=print)  # doesn't work
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/yx-z/forbiddenfp",
    "name": "forbiddenfp",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "",
    "author": "David",
    "author_email": "yx-z <yx-z@outlook.com>",
    "download_url": "https://files.pythonhosted.org/packages/ab/4d/3f8de2487e37101a7275fa434b75777f4619026cea59363320429a536ed1/forbiddenfp-0.9.9.3.tar.gz",
    "platform": null,
    "description": "# forbiddenfp\n\n## Summary\n\nFunctional-Programming (FP) in a forbidden way:\n\nYou can turn arbitrary function into postfix notation in favor of function chaining.\n\nAnd the library provides many useful patches for builtin/itertools functions.\n\n## Install\n\nCompatible with Python 3.7+\n\n```shell\npip install forbiddenfp\n```\n\n## Examples\n\n```python\n# objects are already patched at import time\nimport forbiddenfp\n\n\"abc\".print().len()  # print out \"abc\", then return 3\n\"abc\".then(lambda s: s * 2).filter(lambda s: s == \"b\").join()  # \"bb\"\n\n# A more complex one (examples/word_count.py)\n(\"./lorem_ipsum.txt\"\n .with_open(lambda path, f: f.read().also(print(f\"Reading {path}\")))\n .then(lambda s: s.split(\" \"))\n .counter()\n .print())\n\n```\n\nSee more `./examples`.\n\n## `_unpack`\n\nFor every higher-order-function chained, we provide an `_unpack` version as well.\ne.g. `[(1, 2), (3, 4)].sum(lambda x: x[0] * x[1])`\ncan also be called as `[(1, 2), (3, 4)].sum_unpack(lambda x, y: x * y)`\n\n## Why Functional Programming\n\nSeparate out control structs (which are functions provided by library) from business logic (which are lambda functions\nsupplied to fill the control structs).\n\nSo we can have a clearer scope, and separate concerns, when we want to change on either side of things.\n\n- `if ...` and `if ... else ...` are modeled by Maybe/Either monads.\n- `while ...` and `for ... in ...` are generator/iterators. Additionally, stop-early behavior is `takewhile` of the\n  sequence.\n\nPhilosophically, think more in `def transform(old_state) -> new_state`, rather than `state = modify(state)`.\n\n## What About Auto-completion?\n\nThis library is almost an embedded Domain Specific Language (DSL) in Python.\n\nIt is understandable that users aren't familiar with what is available without auto-completion features in IDEs.\n\nSo we leverage the stub file to provide type hints for the builtin `object` type, which IntelliJ/PyCharm/VsCode all support.\n\n![img_1.png](img_1.png)\n\nIn order to find where to stub, open your IDE and Python project/file, type `object` to get a class, CTRL/CMD + Click and use\n\"Find Definition\" feature to get to the stub file of your IDE plugin.\n\nThen copy/paste `src/forbiddenfp/__init__.py` under `class object` stub.\n\nNote that for IntelliJ/Pycharm, once you CTRL + Click on `object`, you would need to click on the little icon below\nto get to the *actual* stub file. Append content there.\n\n![img.png](img.png)\n\n## Warning\n\nThis library patches builtin `object` (and hence ALL classes),\nwith hacks around CPython API (provided by [forbiddenfruit](https://github.com/clarete/forbiddenfruit)),\n\nso consider this NSFW (Not Safe For Work).\n\n## Known Issues\n\n`None` doesn't work well with chained keyword arguments.\n\n```python\nimport forbiddenfp\n\nNone.apply(print)  # works\nNone.apply(func=print)  # doesn't work\n```\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Forbidden Functional Programming in Python.",
    "version": "0.9.9.3",
    "project_urls": {
        "Homepage": "https://github.com/yx-z/forbiddenfp",
        "Issues": "https://github.com/yx-z/forbiddenfp/issues"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "430c0ff73c0aa49de7ef38d01ef05f35c9439d4a0a756e0ccf2a440fc898277d",
                "md5": "32712a20f8c7fffa9e4f8452182663b7",
                "sha256": "db1a981a94066d107720834c71e6f28646083e36bd26a963a48a43152edf4334"
            },
            "downloads": -1,
            "filename": "forbiddenfp-0.9.9.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "32712a20f8c7fffa9e4f8452182663b7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 8031,
            "upload_time": "2024-02-23T23:26:52",
            "upload_time_iso_8601": "2024-02-23T23:26:52.067624Z",
            "url": "https://files.pythonhosted.org/packages/43/0c/0ff73c0aa49de7ef38d01ef05f35c9439d4a0a756e0ccf2a440fc898277d/forbiddenfp-0.9.9.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ab4d3f8de2487e37101a7275fa434b75777f4619026cea59363320429a536ed1",
                "md5": "fb314ddb174160c8d77a0fec12f72042",
                "sha256": "40e179f232cc32177aa0a3178e70a3cdb2a38f7ec8428b98cd4620b2c6542e5c"
            },
            "downloads": -1,
            "filename": "forbiddenfp-0.9.9.3.tar.gz",
            "has_sig": false,
            "md5_digest": "fb314ddb174160c8d77a0fec12f72042",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 7877,
            "upload_time": "2024-02-23T23:26:53",
            "upload_time_iso_8601": "2024-02-23T23:26:53.844169Z",
            "url": "https://files.pythonhosted.org/packages/ab/4d/3f8de2487e37101a7275fa434b75777f4619026cea59363320429a536ed1/forbiddenfp-0.9.9.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-23 23:26:53",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "yx-z",
    "github_project": "forbiddenfp",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "forbiddenfruit",
            "specs": []
        },
        {
            "name": "typing_extensions",
            "specs": []
        }
    ],
    "lcname": "forbiddenfp"
}
        
Elapsed time: 0.18027s