Skip to main content

coppertop - multiple-dispatch, partial functions and pipeline style for Python

Coppertop provides an alternative programming experience in Python via the following:

  • multiple-dispatch
  • partial functions
  • piping syntax
  • an embryonic core library of common functions

Installation

pip install coppertop-bones-libs for the dm core library and the @coppertop decorator.
pip install coppertop just for the @coppertop decorator.

At the moment needs to be git cloned and the setup.py manually run.


Multiple-dispatch

To use multiple-dispatch decorate functions with @coppertop and use different type annotations. Missing annotations are taken as fallback wildcards. Class inheritance is ignored when matching caller and function signatures.

from coppertop.pipe import *

@coppertop
def addOne(x:int) -> int:
    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()

assert addOne(1) == 2
assert addOne('Three Two ') == 'Three Two One'
assert addOne([0]) == [0, 1]

Partial (application of) functions

syntax: f(_, a) -> f(_)
where _ is used as a sentinel place-holder for arguments yet to be confirmed (TBC)

We create partials of @coppertop decorated functions when we use _ indicating deferred arguments. For example:

from coppertop.pipe import *

@coppertop
def appendStr(x, y):
    assert isinstance(x, str) and isinstance(y, str)
    return x + y

appendWorld = appendStr(_, " world!")           # first argument is deferred

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 easier to express program syntax (aka sequence).


unary style - takes 1 piped argument and 0+ called arguments

syntax: A >> f(args) -> f(args)(A)

from coppertop.pipe import *

@coppertop(style=unary)
def addOne(x):
    return x + 1

1 >> addOne
"hello" >> appendStr(_," ") >> appendStr(_, "world!")

1 >> partial(lambda x: x +1)

binary style - takes 2 piped arguments and 0+ called arguments

syntax: A >> f(args) >> B -> f(args)(A, B)

from bones.core.errors import NotYetImplemented
from dm.core import collect, 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] >> collect >> (lambda x: x + 1)
[1,2,3] >> inject(_,0,_) >> (lambda x,y: x + y)

ternary style - takes 3 piped arguments and 0+ called arguments

syntax: A >> f(args) >> B >> C -> f(args)(A, B, C)

from dm.core import both
from dm.testing immport check, equals

actual = [1,2] >> both >> (lambda x, y: x + y) >> [3,4]
assert (1 >> equal >> 1) == True
actual >> check >> equal >> [4, 6]

Examples

Bag of M&Ms problem

In Why coppertop - MM problem from Think Bayes.ipynb we implement a coppertop solution to the problem and silently introduce intersection types.

Cluedo notepad

See algos.py, where we track a game of Cluedo and infer who did it. See ex_games.py and cluedo-pad.ipynb for example game input and notepad output.


a whimsical exercise for the ambitious

(both, collect, inject, addOne, appendStr, check, equals are all illustrated above)

from dm.core import to
[1,2] >> both >> (lambda x, y: x + y) >> [3,4] 
   >> collect >> (lambda x: x * 2)
   >> inject(_,1,_) >> (lambda x,y: x * y)
   >> addOne >> addOne >> addOne
   >> to >> str >> appendStr(_," red balloons go by")
   >> check >> equal >> ???

Other


Thanks

Inspired by

Built using

Metadata

Release files for coppertop-bones 2025.6.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for coppertop-bones 2025.6.8
File Size Uploaded Provenance Actions
coppertop_bones-2025.6.8.tar.gz 68.8 kB Without provenance Details for coppertop_bones-2025.6.8.tar.gz

Release files / coppertop_bones-2025.6.8.tar.gz

Download URL coppertop_bones-2025.6.8.tar.gz
Size 68.8 kB
Tags Source
SHA-256 checksum
How to use checksums
5d882e0f89a2761b8328c79a3560cd47f4e6a90d391ece65f7ee7893c34b6865
BLAKE2b-256 checksum
How to use checksums
b883bb8c65c7fc42caa45110e6f1daa614ba6126cdefedd41a20483f0dbfd8de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.0

Security for coppertop-bones 2025.6.8

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2025.6.8 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page