{"id":13648390,"url":"https://github.com/czheo/syntax_sugar_python","last_synced_at":"2025-04-12T11:14:44.121Z","repository":{"id":57472946,"uuid":"79616952","full_name":"czheo/syntax_sugar_python","owner":"czheo","description":"A library adding some anti-Pythonic syntatic sugar to Python","archived":false,"fork":false,"pushed_at":"2021-05-23T20:24:33.000Z","size":95,"stargazers_count":735,"open_issues_count":2,"forks_count":23,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-12T11:14:23.032Z","etag":null,"topics":["functional","parallelism","pipeline","python","syntax-sugar"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/czheo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-21T02:04:01.000Z","updated_at":"2025-04-10T09:38:32.000Z","dependencies_parsed_at":"2022-09-26T17:40:45.139Z","dependency_job_id":null,"html_url":"https://github.com/czheo/syntax_sugar_python","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/czheo%2Fsyntax_sugar_python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/czheo%2Fsyntax_sugar_python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/czheo%2Fsyntax_sugar_python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/czheo%2Fsyntax_sugar_python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/czheo","download_url":"https://codeload.github.com/czheo/syntax_sugar_python/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248557843,"owners_count":21124168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional","parallelism","pipeline","python","syntax-sugar"],"created_at":"2024-08-02T01:04:12.166Z","updated_at":"2025-04-12T11:14:43.892Z","avatar_url":"https://github.com/czheo.png","language":"Python","readme":"# syntax_sugar [![travis_status](https://travis-ci.org/czheo/syntax_sugar_python.svg?branch=master)](https://travis-ci.org/czheo/syntax_sugar_python) [![PyPI](https://img.shields.io/pypi/v/syntax_sugar.svg)](https://pypi.python.org/pypi/syntax_sugar)\n\nThis lib adds some anti-Pythonic \"syntactic sugar\" to Python.\n\nNOTE: This is merely an experimental prototype to show some potential of operator overloading in Python. Only tested under Python 3.6.0. Anything may evolve without announcement in advance.\n\nInspired by https://github.com/matz/streem. \n\nAlso, you can watch the last part of this Matz's talk to understand the intuition behind this project.\n\n[![Stream Model](https://img.youtube.com/vi/48iKjUcENRE/0.jpg)](https://youtu.be/48iKjUcENRE?t=39m29s)\n\n# Install\n```\npip install syntax_sugar\n```\n\n# Use\n\nTo test out this lib, you can simply do.\n\n``` python\nfrom syntax_sugar import *\n```\n\nFor serious use, you can explicitly import each component as explained below ... if you dare to use this lib. \n\n### pipe\n``` python\nfrom syntax_sugar import pipe, END\nfrom functools import partial\n\npipe(10) | range | partial(map, lambda x: x**2) | list | print | END\n# put 10 into the pipe and just let data flow.\n# output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n# remember to call END at the end\n# NOTE: everything in the middle of the pipe is just normal Python functions\n\npipe(10) | range | (map, lambda x: x**2) | list | print | END\n# Tuples are shortcuts for partial functions\n\nfrom syntax_sugar import each\nx = pipe(10) | range | each(lambda x: x ** 2) | END\n# We can also save the result in a variable.\n# `each` is an eager evaluated version of the partial function of `map`, which returns a list instead of a map object. (Equivalent to `map` in Python 2)\n\npipe(10) | range | each(str) | ''.join \u003e 'test.txt'\n# wanna write to a file? Why not!\n# write \"0123456789\" to test.txt\n# We don't need to put END here.\n```\n\nWe can connect multiple pipes to create a longer pipe\n\n``` python\nfrom syntax_sugar import pipe, each, END\nfrom functools import reduce\n\np1 = pipe(10) | range | each(lambda x: x/2)\n# head pipe can have input value\np2 = pipe() | (reduce, lambda acc, x: (acc + x)/2)\np3 = pipe() | int | range | sum\n# middle pipes can have no input value\n\np1 | p2 | p3 | END\n# returns 6\n\n\np = p1 | p2 | p3\np()\n# You can invoke the pipe by calling it as a function\n\n# you can also put a different value in the pipe\np(20)\n# returns 36\n```\n\n### pipe with parallelism\n\nBy default, pipe works with threads.\n\nYou can have a function running in a seperate thread with pipe. Just put it in a `[]` or more explicitly `t[]`. Threads and processes are also available.\n\n``` python\nfrom syntax_sugar import (thread_syntax as t,\n                          process_syntax as p)\n\npipe(10) | [print] | END   # print run in a thread\npipe(10) | t[print] | END  # print run in a thread\npipe(10) | p[print] | END  # print run in a process\n```\n\nWhat makes this syntax good is that you can specify how many threads you want to spawn, by doing `[function] * n` where `n` is the number of threads.\n\n``` python\npipe([1,2,3,4,5]) | [print] * 3 | END # print will run in a ThreadPool of size 3\n```\n\nHere is an example of requesting a list of urls in parallel\n\n``` python\nimport requests\n(pipe(['google', 'twitter', 'yahoo', 'facebook', 'github'])\n    | each(lambda name: 'http://' + name + '.com')\n    | [requests.get] * 3   # !! `requests.get` runs in a ThreadPool of size 3\n    | each(lambda resp: (resp.url, resp.headers.get('Server')))\n    | list\n    | END)\n\n# returns\n# [('http://www.google.com/', 'gws'),\n#  ('https://twitter.com/', 'tsa_a'),\n#  ('https://www.yahoo.com/', 'ATS'),\n#  ('https://www.facebook.com/', None),\n#  ('https://github.com/', 'GitHub.com')]\n```\n\n### infix function\n``` python\nfrom syntax_sugar import is_a, has, to, step, drop\n\n1 /is_a/ int\n# equivalent to `isinstance(1, int)`\n\n1 /as_a/ str\n# \"1\"\n\nrange(10) /has/ '__iter__'\n# equivalent to `hasattr(range(10), \"__iter__\")`\n\n1 /to/ 10\n# An iterator similar to `range(1, 11)`.\n# Python's nasty range() is right-exclusive. This is right-inclusive.\n\n10 /to/ 1\n# We can go backward.\n\n'0' /to/ '9'\n# We can also have a range of characters :)\n\n1 /to/ 10 /step/ 2\n# We can also specify step sizes.\n# Similar to `range(1, 11, 2)`\n\n10 /to/ 1 /step/ 2\n# Go backward.\n# Similar to `range(10, 0, -2)`\n\n1 /to/ 10 /drop/ 5\n# there is a `drop` functon which drop N items from the head\n# An iterator similar to [6, 7, 8, 9, 10]\n```\n\n`/to/` has some advanced features\n\n- lazy evaluation.\n- support infinity.\n- support product operation.\n- support pipe.\n\n``` python\nfrom syntax_sugar import INF, take, each\n\n# CAUTION: this will infinitely print numbers\nfor i in 1 /to/ INF:\n    print(i)\n\n1 /to/ INF /take/ 5 /as_a/ list\n# there is a `take` functon which is similar to itertools.islice\n# return [1, 2, 3, 4, 5]\n\n1 /to/ ... /take/ 5 /as_a/ list\n# ... is equivalent to INF\n\n0 /to/ -INF /step/ 2 /take/ 5 /as_a/ list\n# also works with negative infinity.\n# return [0, -2, -4, -6, -8]\n\n(1 /to/ 3) * (4 /to/ 6) /as_a/ list\n# all combinations of [1..3] * [4..6]\n# return [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]\n\n1 /to/ 10 /take/ 5 | each(lambda x: x **2) | END\n# These infix functions can also be piped.\n# [1, 4, 9, 16, 25]\n```\n\nMake your own infix function, so you can append multiple items to a list in one line.\n\n``` python\nfrom syntax_sugar import infix\n\n@infix\ndef push(lst, x):\n    lst.append(x)\n    return lst\n\n[] /push/ 1 /push/ 2 /push/ 3\n# returns [1,2,3]\n```\n\nYou can also do\n\n``` python\ndef push(lst, x):\n    lst.append(x)\n    return lst\n\nipush = push /as_a/ infix\n\n[] /ipush/ 1 /ipush/ 2 /ipush/ 3\n# returns [1,2,3]\n```\n\n\u003c!---\n### stream\n\n``` python\nfrom syntax_sugar import stream, take\n\nlist(stream() \u003c\u003c [1,2,3] \u003c\u003c range(5))\n# [1,2,3,0,1,2,3,4]\n# stream will connect all sequences together\n\nlist((stream() \u003c\u003c [1, 1] \u003c\u003c (lambda x, y: x + y)) /take/ 10)\n# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n# This is the first 10 items of an infinite fibonacci stream\n# If a function is met, stream will infinitely take the last N previous items as the input of the lambda to generate the next item.\n```\n--\u003e\n\n\n### function composition\n\nIn math, `(f * g) (x) = f(g(x))`. This is called function composition.\n\n``` python\n# lmap equivalent to `list(map(...))`\nlmap = compose(list, map)\nlmap(lambda x: x ** 2, range(10))\n```\n\nLet's say we want to represent `f * g * h` in a program, i.e. `fn(x) = f(g(h(x)))`\n\n``` python\nf = lambda x: x**2 + 1\ng = lambda x: 2*x - 1\nh = lambda x: -2 * x**3 + 3\n\nfn = compose(f, g, h)\n\nfn(5) # 245026\n```\n\nor you can do\n\n```python\nf = composable(lambda x: x**2 + 1)\ng = composable(lambda x: 2*x - 1)\nh = composable(lambda x: -2 * x**3 + 3)\n\nfn = f * g * h\n\nfn(5) # 245026\n```\n\nSometimes you may prefer the decorator way.\n\n``` python\n# make your own composable functions\n@composable\ndef add2(x):\n    return x + 2\n\n@composable\ndef mul3(x):\n    return x * 3\n\n@composable\ndef pow2(x):\n    return x ** 2\n    \nfn = add2 * mul3 * pow2\n# equivalent to `add2(mul3(pow2(n)))`\nfn(5)\n# returns 5^2 * 3 + 2 = 77\n```\n\nMore receipes: https://github.com/czheo/syntax_sugar_python/tree/master/recipes\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fczheo%2Fsyntax_sugar_python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fczheo%2Fsyntax_sugar_python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fczheo%2Fsyntax_sugar_python/lists"}