Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 74 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,68 @@ problem](https://projecteuler.net/problem=2):
Given `fib` a generator of Fibonacci numbers:

```python
sum(fib() | where(lambda x: x % 2 == 0) | take_while(lambda x: x < 4000000))
```

Each pipes is lazy evalatated, can be aliased, and partially
initialized, so it could be rewritten as:

```python
is_even = where(lambda x: x % 2 == 0)
sum(fib() | is_even | take_while(lambda x: x < 4000000)
```
>>>sum(fib() | where(lambda x: x % 2 == 0) | take_while(lambda x: x < 4000000))
```

Each pipe is evaluated lazily, can be assigned an alias,
and supports partial initialization, allowing it to be rewritten as:

```python
>>>is_even = where(lambda x: x % 2 == 0)
>>>sum(fib() | is_even | take_while(lambda x: x < 4000000)
```

# Table of Contents

- [Installing](#installing)
- [Using](#using)
- [Existing Pipes in this module](#existing-pipes-in-this-module)
- [`batched`](#batched)
- [`chain`](#chain)
- [`chain_with(other)`](#chain_withother)
- [`dedup(key=None)`](#dedupkeynone)
- [`enumerate(start=0)`](#enumeratestart0)
- [`filter(predicate)`](#filterpredicate)
- [`groupby(key=None)`](#groupbykeynone)
- [`islice()`](#islice)
- [`izip()`](#izip)
- [`map()`, `select()`](#map-select)
- [`netcat`](#netcat)
- [`permutations(r=None)`](#permutationsrnone)
- [`reverse`](#reverse)
- [`select(fct)`](#selectfct)
- [`skip()`](#skip)
- [`skip_while(predicate)`](#skip_whilepredicate)
- [`sort(key=None, reverse=False)`](#sortkeynone-reversefalse)
- [`t`](#t)
- [`tail(n)`](#tailn)
- [`take(n)`](#taken)
- [`take_while(predicate)`](#take_whilepredicate)
- [`tee`](#tee)
- [`transpose()`](#transpose)
- [`traverse`](#traverse)
- [`uniq(key=None)`](#uniqkeynone)
- [`where(predicate)`, `filter(predicate)`](#wherepredicate-filterpredicate)
- [Constructing your own](#constructing-your-own)
- [One-off pipes](#one-off-pipes)
- [Euler project samples](#euler-project-samples)
- [Going deeper](#going-deeper)
- [`Partial pipes`](#partial-pipes)
- [`Lazy Evaluation`](#lazy-evaluation)
- [`Deprecations`](#deprecations)


# Installing

There is no need to clone the repository as Pipe is available through PyPI.
To install the library, you can just run the following command:

```shell
# Linux/macOS
python3 -m pip install pipe
>>>python3 -m pip install pipe

# Windows
py -3 -m pip install pipe
>>>py -3 -m pip install pipe
```


Expand Down Expand Up @@ -123,10 +163,10 @@ Chain a sequence of iterables:
Warning : chain only unfolds an iterable containing ONLY iterables:

```python
list([1, 2, [3]] | chain)
>>>list([1, 2, [3]] | chain)
```
Gives a `TypeError: 'int' object is not iterable`
Consider using traverse.
Consider using traverse for nested iterables.


### `chain_with(other)`
Expand Down Expand Up @@ -229,13 +269,13 @@ to each element of the given iterable
The netcat Pipe sends and receive bytes over TCP:

```python
data = [
b"HEAD / HTTP/1.0\r\n",
b"Host: python.org\r\n",
b"\r\n",
]
for packet in data | netcat("python.org", 80):
print(packet.decode("UTF-8"))
>>>data = [
>>> b"HEAD / HTTP/1.0\r\n",
>>> b"Host: python.org\r\n",
>>> b"\r\n",
>>>]
>>>for packet in data | netcat("python.org", 80):
>>> print(packet.decode("UTF-8"))
```

Gives:
Expand Down Expand Up @@ -331,7 +371,7 @@ Like Python's built-in "sorted" primitive.

### `t`

Like Haskell's operator ":":
Creates a sequence by appending elements like Haskell’s ":" operator:

```python
>>> from pipe import t
Expand Down Expand Up @@ -487,9 +527,9 @@ Don't forget they can be aliased:
You can construct your pipes using the `Pipe` class like:

```python
from pipe import Pipe
square = Pipe(lambda iterable: (x ** 2 for x in iterable))
map = Pipe(lambda iterable, fct: builtins.map(fct, iterable)
>>>from pipe import Pipe
>>>square = Pipe(lambda iterable: (x ** 2 for x in iterable))
>>>map = Pipe(lambda iterable, fct: builtins.map(fct, iterable)
>>>
```

Expand All @@ -504,7 +544,7 @@ argument, making the wrapping straight forward:
>>>
```

and that's it `itrable | end(3)` is `deque(iterable, 3)`:
and that's it `iterable | end(3)` is `deque(iterable, 3)`:

```python
>>> list(range(100) | end(3))
Expand Down Expand Up @@ -582,7 +622,7 @@ list(range(20) | Pipe(compress, selectors=[1, 0] * 10))
> exceed four million.

```python
sum(fib() | where(lambda x: x % 2 == 0) | take_while(lambda x: x < 4000000))
>>>sum(fib() | where(lambda x: x % 2 == 0) | take_while(lambda x: x < 4000000))
```

> Find the difference between the sum of the squares of the first one
Expand Down Expand Up @@ -611,14 +651,14 @@ A `pipe` can be parametrized without being evaluated:
For multi-argument pipes then can be partially initialized, you can think of curying:

```python
some_iterable | some_pipe(1, 2, 3)
some_iterable | Pipe(some_func, 1, 2, 3)
>>>some_iterable | some_pipe(1, 2, 3)
>>>some_iterable | Pipe(some_func, 1, 2, 3)
```

is strictly equivalent to:

```python
some_iterable | some_pipe(1)(2)(3)
>>>some_iterable | some_pipe(1)(2)(3)
```

So it can be used to specialize pipes, first a dummy example:
Expand Down Expand Up @@ -760,13 +800,13 @@ one returning non-iterables could only be used as the last function of
a pipe expression, so they are in fact useless:

```python
range(100) | where(lambda x: x % 2 == 0) | add
>>>range(100) | where(lambda x: x % 2 == 0) | add
```

can be rewritten with no less readability as:

```python
sum(range(100) | where(lambda x: x % 2 == 0))
>>>sum(range(100) | where(lambda x: x % 2 == 0))
```

so all pipes returning non-iterables were deprecated (raising
Expand Down Expand Up @@ -808,3 +848,5 @@ feel free to implement them on your project, and consider the
already-implemented ones as examples on how to do it.

See the `Constructing your own` paragraph below.

- [Constructing your own](#constructing-your-own)