# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['functionali']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'functionali',
    'version': '0.2.0',
    'description': 'Functional programming tools for python. Putting the fun in functional programming 😉',
    'long_description': '# Functionali\nfunctional programming tools for python. Putting the fun in functional programming 😉\n\n[![codecov](https://codecov.io/gh/AbhinavOmprakash/functionali/branch/main/graph/badge.svg?token=75LLE4F7EY)](https://codecov.io/gh/AbhinavOmprakash/functionali)\n[![Documentation Status](https://readthedocs.org/projects/functionali/badge/?version=latest)](https://functionali.readthedocs.io/en/latest/?badge=latest)\n      \n\nFunctional programming is a fundamentally different way of solving problems, and once It clicks, it\'s pure joy after that. \nA lot of ideas in this library have been taken from Clojure and Haskell, so the credit goes to those languages. \nIf you find your favorite function missing, or find ways to improve this project, I\'d love to hear it.\n\n\n\n[Documentation](https://functionali.readthedocs.io/en/latest/)\n\n[wiki](https://functionali.readthedocs.io/en/latest/)\n\n## Installation\n```bash \npip install functionli \n```\n\n## Features\n- Polymorphic functions that operate on all sequences. Including dictionaries.\n- A bunch of commonly used predicates that enhance readability, especially when used with filters.\n\n## A note on how functionali deals with dictionaries.\nAs of now, all sequence traversing like `first` and `rest` functions treat dictionaries as a nested tuple of keys and values. \nHere\'s an example. \n\n```pycon\n>>> d = {1:"a"}\n>>> first(d)\n((1, "a"),)\n```\n\nwhile this is convenient for traversing dicts, it makes certain functions like `contains` rather awkward, since you as the user, would \nhave to explicity convert the tuple back to a dict before passing it in. \n(This might change in future)\n\n\n\n## functional programming is powerful\n \nOne of my favorite Functional implementations of an algorithm is insertion sort, here\'s how simple it \n```pycon\n>>> from functionali import foldr, insert\n>>> def insertion_sort(iterable):\n...     return foldr(insert, iterable, [])\n\n>>> insertion_sort([3,2,1])\n(1, 2, 3)\n\n# even works with dictionaries\n>>> insertion_sort({3:"c", 1: "a", 2: "b"})  \n((1, \'a\'), (2, \'b\'), (3, \'c\'))\n\n# and strings\n>>> insertion_sort("cbdasdf")\n(\'a\', \'b\', \'c\', \'d\', \'d\', \'f\', \'s\')\n>>> "".join(insertion_sort("cbdasdf"))\n\'abcddfs\' # better?\n``` \n\n## functional programs are flexible\n\nLet\'s say you wanted to find a number that was divisible by The following numbers\n`1,2,3,4,5,6,7,8,9,10` \nOne way to solve it is a bunch of nested `if` Statements and we all know how brittle those can be.\n\nLet\'s see the functional way.\n```pycon\n>>> from functionali import is_divisible_by, all_predicates\n>>> my_filter = all_predicates(*map(is_divisible_by,[1,2,3,4,5,6,7,8,9,10]))\n>>> list(filter(my_filter,range(1,10000)))\n[2520, 5040, 7560]\n```\n\nNow let\'s say the boss decides that He wants the numbers that are not \nDivisible by all these numbers\n```pycon\n>>> from functionali import complement\n>>> list(filter(complement(my_filter),range(1,10000)))\n[... 2515, 2516, 2517, 2518, 2519, 2521, 2522, 2523, 2524...] # Snipped for brevity \n# note that 2520 is not present\n```\nThe boss comes in again and he says that he Doesn\'t want numbers that are divisible by ALL these numbers but instead, ANY of these numbers `[1,2,3,4,5,6,7,8,9,10]`\n```pycon\n>>> from functionali import some_predicates\n>>> my_filter = some_predicates(*map(is_divisible_by,[1,2,3,4,5,6,7,8,9,10]))\n>>> list(filter(complement(my_filter),range(1,10000)))\n[]\n```\nThe boss realizes that all numbers are divisible by 1 and he tells you to Remove 1\n\n```pycon\n>>> my_filter = some_predicates(*map(is_divisible_by,[2,3,4,5,6,7,8,9,10]))   \n>>> list(filter(complement(my_filter),range(1,10000)))\n[1, 11, 13, 17, 19, 23, 29, 31...] # ,Snipped for brevity\n```\n\n## A few more examples\n\nFunctionali provides functions to traverse sequences(Including dictionaries), Some of the most useful ones are `first`, `rest`, `last`,`butlast`, `take`, `drop`\n```Python\nfrom functionali import first, rest, last, butlast, take, drop\n\n>>> first([1,2,3,4,5])\n    1\n\n>>> first({1:"a", 2:"b"})\n    (1, "a")\n\n>>> last([1,2,3,4])\n    4\n\n>>> list(rest([1,2,3,4,5]))\n    [2, 3, 4, 5]\n\n>>> butlast([1,2,3]) # returns all elements except the last element\n    (1,2)\n\n>>> take(3, [1,2,3,4,5])\n    (1, 2, 3)\n\n>>> drop(3, [1,2,3,4,5])\n    (4,5)\n```\n\nThere are functions that construct new sequences like `cons`, `conj`, `concat`, `insert`\n\n```Python\nfrom functionali import cons, conj, concat, insert\n>>> cons(5, [1,2,3,4])\n    deque([5, 1, 2, 3, 4]) # 5 is the \'head\' of the new list.\n\n# adds element to the iterable, at the appropriate end.\n>>> conj([1,2,3,4],5) # similar to Clojure\'s conj\n    [1, 2, 3, 4, 5]\n\n    # Adds to the left of a deque.\n>>> conj(deque([1,2]), 3,4)\n    deque([4, 3, 1, 2])\n\n# Add items to the end of the iterable.\n>>> concat([1,2,3,4],5)\n    [1, 2, 3, 4, 5]\n\n>>> concat(deque([1,2]), 3,4)\n    deque([1, 2, 3, 4])\n\n# Inserts 3 right before the first element\n# in the iterable (here:4) that is greater than 3\n>>> insert(3, [1,2,4,2])\n    (1,2,3,4,2)\n```\n\nFunctionali also comes with a number of useful predicates \n(if You can\'t find something you\'re looking for, make a pull request.)\nThese can be combined in various ways.\nfor example.\n\n```Python\nfrom functionali import is_even, is_prime, take_while\n>>> list(filter(is_even,[1,2,3,4])\n    [2,4]\n\n>>> take_while(is_prime, [2,3,5,4,6,5])) # Constructs a list while is_prime is true.\n    [2,3,5]\n\n```\n\n\n\n\n',
    'author': 'Abhinav Omprakash',
    'author_email': None,
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://functionali.readthedocs.io/en/latest/',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
