You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

better-functools

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

better-functools

Functional Programming Ergonomics in Python.

0.2.0
pipPyPI
Maintainers
1

better-functools

Better functools improves functional programming ergonomics in Python

Installation

$ pip install better-functools

Background

The library introduces 2 different operators for use with functions:

  • | which we'll call "pipe"
  • @ which we'll call "apply"

The following is an example:

Pipeline(inputs)
| func(itertools.combinations @ func.arg(Iterable[int]) @ bind(2))
| filter @ bind(sum @ compose(eq @ bind(2020)))
| map @ bind(prod)
| sum
| Pipeline.unwrap

This may look strange but we can break this down.

pipe

Pipeline wraps inputs and enables unix like pipes. So Pipeline(v) | fn is equal to Pipeline(fn(v)).

| Pipeline.unwrap is finally used to unwrap the Pipeline and extract the value.

apply

better_functools.apply includes a number of functions that implements @.

For example, map @ bind(prod) means bind prod to the first arg of map. More apply functions can be called directly too, the above expression is equivalent to bind(prod)(map).

The usual pattern is: some_value @ some_operator(args)

The @ operator takes some getting used to, but the main benefit is how chainable operators are.

add @ bind(1) @ bind(2)

reads left to right fairly well, but if we were to call directly:

bind(2)(bind(1)(add))

It's just a lot harder to read and we need more brackets.

Putting @ and | together

You can see that @ and | both facilitate some sort of "function chaining". So why add 2 different operators?

@ is higher precedence than | so it can be used in each stage of a pipe without brackets. Generally the idea is to use @ operators to build the function for each stage of a |.

Without @ functions are a lot harder to build inline and often must be defined explicitly elsewhere.

General Tips

Type Checking

  • The typing here is built for Pyright.
  • Mypy compatibility is okay, specific issues with mypy are highlighted in function docs.
  • Other type checkers simply lack the popularity for me to support actively.

functools.partial

Feel free to use functools.partial to create partial functions in place of bind and func. Both MyPy and Pyright has a custom type checking handler for partial. This is the best way to bind keyword arguments right now.

partial(itertools.combinations, r=2)

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts