Piping and multi-dispatch for python
Project description
coppertop - piping and multi-dispatch for python
Coppertop provides a bones-style aggregation manipulation experience in python via the following:
- partial (application of) functions
- piping syntax
- multiple-dispatch
- type system with primitives, intersections, unions, products, exponentials, overloads and type schemas thus allowing Python to be a library implementation language for bones
- immutable updates
- contextual scope
- and an embryonic core library of common pipeable functions
Partial (application of) functions
By decorating a function with @coppertop (and importing _) we can easily create partial functions, for example:
syntax: f(_, a)
-> f(_)
where _
is used as a sentinel place-holder for arguments yet to be confirmed (TBC)
from coppertop.pipe import *
@coppertop
def appendStr(x, y):
assert isinstance(x, str) and isinstance(y, str)
return x + y
appendWorld = appendStr(_, " world!")
assert appendWorld("hello") == "hello world!"
Piping syntax
The @coppertop function decorator also extends functions with the >>
operator
and so allows code to be written in a more essay style format - i.e. left-to-right and
top-to-bottom. The idea is to make it easy to express the syntax (aka sequence) of a solution.
unary style - takes 1 piped argument and 0+ called arguments
syntax: A >> f(args)
-> f(args)(A)
from dm.std import anon
@coppertop
def addOne(x):
return x + 1
1 >> addOne
"hello" >> appendStr(_," ") >> appendStr(_, "world!")
1 >> anon(lambda x: x +1)
binary style - takes 2 piped argument and 0+ called arguments
syntax: A >> f(args) >> B
-> f(args)(A, B)
from coppertop.core import NotYetImplemented
from dm.std import each, inject
@coppertop(style=binary)
def add(x, y):
return x + y
@coppertop(style=binary)
def op(x, action, y):
if action == "+":
return x + y
else:
raise NotYetImplemented()
1 >> add >> 1
1 >> op(_,"+",_) >> 1
[1,2] >> each >> (lambda x: x + 1)
[1,2,3] >> inject(_,0,_) >> (lambda x,y: x + y)
ternary style - takes 3 piped argument and 0+ called arguments
syntax: A >> f(args) >> B >> C
-> f(args)(A, B, C)
from dm.std import both, check, equal
[1,2] >> both >> (lambda x, y: x + y) >> [3,4] >> check >> equal >> [4, 6]
as an exercise for the reader
[1,2] >> both >> (lambda x, y: x + y) >> [3,4]
>> each >> (lambda x: x * 2)
>> inject(_,1,_) >> (lambda x,y: x * y)
>> addOne >> addOne >> addOne
>> to(_,str) >> appendStr(" red balloons go by")
>> check >> equal >> ???
Multiple-dispatch
Just redefine functions with different type annotations. Missing annotations are taken as fallback wildcards. Class inheritance is ignored when matching caller and function signatures.
@coppertop
def addOne(x:idx) -> idx:
return x + 1
@coppertop
def addOne(x:str) -> str:
return x + 'One'
@coppertop
def addOne(x): # fallback
if isinstance(x, list):
return x + [1]
else:
raise NotYetImplemented()
1 >> addOne >> check >> equal >> 2
'Three Two ' >> addOne >> check >> equal >> 'Three Two One'
[0] >> addOne >> check >> equal >> [0, 1]
Type system
As an introduction, consider:
from ribs.types import BTAtom, S, num, idx, str, O
num = BTAtom.ensure('num') # nominal
_ccy = BTAtom.ensure('_ccy') # nominal
ccy = num & _ccy # intersection
ccy + null # union
ccy * idx * str # tuple (sequence of types)
S(name=str, age=num) # struct
N ** ccy # collection of ccy accessed by an ordinal (N)
str ** ccy # collection of ccy accessed by a python string
(num*num) ^ num # (num, num) -> num - a function
T, T1, T2, ... # type variable - to be inferred at build time
I(domestic=ccy&T, foreign=ccy&T) # named intersection (aka discrimated type)
Example - Cluedo notepad
See algos.py, where we track a game of Cluedo and make inferences for who did it. See games.py for example game input.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Hashes for coppertop-bones-2022.7.30.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | ce3fd6be841170979d30fa9b0b2cd244a24768c822b202074c509c3540c3f59d |
|
MD5 | 0013649b32de75cf5ea221ec836cf37c |
|
BLAKE2b-256 | 642e2504ec57f09370f56b3edf99b6e2c171a68414fff7616f8e60a4eb84d679 |