From 892fc07a4a8a5737f97ce0267ecc887743463877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Fr=C4=85cek?= Date: Mon, 13 Nov 2023 10:06:01 +0100 Subject: [PATCH] corrected homepage --- docs/index.md | 119 +++++++++++++-- mkdocs.yml | 4 + site/index.html | 159 ++++++++++++++++---- site/lazy/index.html | 119 +++++++-------- site/qlist/index.html | 332 ++++++++++++++++++++++-------------------- site/sitemap.xml.gz | Bin 127 -> 127 bytes src/qwlist/qwlist.py | 8 + 7 files changed, 487 insertions(+), 254 deletions(-) diff --git a/docs/index.md b/docs/index.md index 000ea34..8b48116 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,17 +1,112 @@ -# Welcome to MkDocs +# Qwery List +Qwery List is a small library introducing a new way to use higher order functions +with lists, with **lazy evaluation**. -For full documentation visit [mkdocs.org](https://www.mkdocs.org). +### Quick comparison +#### The standard python way +```python +xs = ['1', '2', '3', '4'] +s = reduce(lambda acc, x: acc + x, filter(lambda x: x < 3, map(int, xs)), 0) +``` +#### Qwery List way +```python +xs = QList(['1', '2', '3', '4']) +s = xs.map(int).filter(lambda x: x < 3).fold(lambda acc, x: acc + x, 0) +``` +Chaining methods makes code much more readable and follows the natural flow +of reading left to right. +As a bonus you get `len()` **method**, so no longer will you be forced to wrapp your +lists in this type of code `len(xs)` and simply call `xs.len()` (I understand it is negligibly +slower but look how much nicer it looks!) -## Commands +--- -* `mkdocs new [dir-name]` - Create a new project. -* `mkdocs serve` - Start the live-reloading docs server. -* `mkdocs build` - Build the documentation site. -* `mkdocs -h` - Print help message and exit. +# Installation +This package is available on [PyPI](https://pypi.org/project/qwlist/) +``` +pip install qwlist +``` + +--- + +# Quick tutorial +Let's say we want to read numbers from a file and choose only the even ones. No problem at all! +```python +from qwlist import QList + +with open('path/to/file.txt', 'r') as file: + qlist = QList(file.readlines()) +even = qlist.map(int).filter(lambda x: x % 2 == 0).collect() +``` +Why is there this `collect` at the end? Because all operations on the QList are **lazy evaluated**, +so in order to finally apply all the operations you need to express that. + +There is also an eagerly evaluated `EagerQList` in case all the actions performed on the list should +be evaluated instantaneously. This object is in the `qwlist.eager` module, but it is also +possible to transform `QList` into `EagerQList` simply by calling `eager()` +```python +>>> from qwlist import QList +>>> QList(range(3)).eager().map(str) +['0', '1', '2'] +``` +EagerQList has the same methods that QList has (`filter`, `map`, `foreach`, ...) but not lazy evaluated so +there is no need to call `collect` at the end. + +--- +# Examples +Making QList from an iterable +```python +>>> QList([1, 2, 3, 4]) +[1, 2, 3, 4] +``` +Making QList from a generator +```python +>>> QList(range(3)) +[0, 1, 2] +``` +Making a list of pairs: `int` and `str` +```python +>>> qlist = QList([1, 2, 3]) +>>> qlist.zip(qlist.map(str)).collect() +[(1, '1'), (2, '2'), (3, '3')] +``` +Summing only the even numbers +```python +>>> QList(range(10)).filter(lambda x: x % 2 == 0).fold(lambda acc, x: acc + x, 0) +20 +``` +--- + +## Side note +This syntax resembles **Rust** syntax: + + + + + + + + + + +
RustPython
+ +```rust +let xs = vec![1, 2, 3, 4]; +let double_xs: Vec = xs.iter().map(|&x| x * 2).collect(); +println!("{double_xs:?}"); +// [2, 4, 6, 8] +``` + + + +```python +xs = QList([1, 2, 3, 4]) +double_xs = xs.map(lambda x: x * 2).collect() +print(double_xs) +# [2, 4, 6, 8] +``` + +
-## Project layout - mkdocs.yml # The configuration file. - docs/ - index.md # The documentation homepage. - ... # Other markdown pages, images and other files. diff --git a/mkdocs.yml b/mkdocs.yml index 2145ccf..afaee30 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,6 +17,10 @@ theme: toggle: icon: material/weather-night name: Switch to dark mode + icon: + repo: fontawesome/brands/github + repo_url: https://github.com/WitoldFracek/qlist/tree/main + nav: - Home: index.md diff --git a/site/index.html b/site/index.html index a4d631d..9e5e986 100644 --- a/site/index.html +++ b/site/index.html @@ -75,7 +75,7 @@
- + Skip to content @@ -235,17 +235,30 @@ @@ -386,17 +399,30 @@ @@ -414,21 +440,100 @@ -

Welcome to MkDocs

-

For full documentation visit mkdocs.org.

-

Commands

- -

Project layout

-
mkdocs.yml    # The configuration file.
-docs/
-    index.md  # The documentation homepage.
-    ...       # Other markdown pages, images and other files.
+

Qwery List

+

Qwery List is a small library introducing a new way to use higher order functions +with lists, with lazy evaluation.

+

Quick comparison

+

The standard python way

+
xs = ['1', '2', '3', '4']
+s = reduce(lambda acc, x: acc + x, filter(lambda x: x < 3, map(int, xs)), 0)
+
+

Qwery List way

+
xs = QList(['1', '2', '3', '4'])
+s = xs.map(int).filter(lambda x: x < 3).fold(lambda acc, x: acc + x, 0)
 
+

Chaining methods makes code much more readable and follows the natural flow +of reading left to right. +As a bonus you get len() method, so no longer will you be forced to wrapp your +lists in this type of code len(xs) and simply call xs.len() (I understand it is negligibly +slower but look how much nicer it looks!)

+
+

Installation

+

This package is available on PyPI

+
pip install qwlist
+
+
+

Quick tutorial

+

Let's say we want to read numbers from a file and choose only the even ones. No problem at all!

+
from qwlist import QList
+
+with open('path/to/file.txt', 'r') as file:
+    qlist = QList(file.readlines())
+even = qlist.map(int).filter(lambda x: x % 2 == 0).collect()
+
+

Why is there this collect at the end? Because all operations on the QList are lazy evaluated, +so in order to finally apply all the operations you need to express that.

+

There is also an eagerly evaluated EagerQList in case all the actions performed on the list should +be evaluated instantaneously. This object is in the qwlist.eager module, but it is also +possible to transform QList into EagerQList simply by calling eager()

+
>>> from qwlist import QList
+>>> QList(range(3)).eager().map(str)
+['0', '1', '2']
+
+

EagerQList has the same methods that QList has (filter, map, foreach, ...) but not lazy evaluated so +there is no need to call collect at the end.

+
+

Examples

+

Making QList from an iterable

+
>>> QList([1, 2, 3, 4])
+[1, 2, 3, 4]
+
+

Making QList from a generator

+
>>> QList(range(3))
+[0, 1, 2]
+
+

Making a list of pairs: int and str

+
>>> qlist = QList([1, 2, 3])
+>>> qlist.zip(qlist.map(str)).collect()
+[(1, '1'), (2, '2'), (3, '3')]
+
+

Summing only the even numbers

+
>>> QList(range(10)).filter(lambda x: x % 2 == 0).fold(lambda acc, x: acc + x, 0)
+20
+
+
+

Side note

+

This syntax resembles Rust syntax:

+ + + + + + + + + +
RustPython
+ + +
let xs = vec![1, 2, 3, 4];
+let double_xs: Vec<i32> = xs.iter().map(|&x| x * 2).collect();
+println!("{double_xs:?}");
+// [2, 4, 6, 8]
+
+ + +
+ + +
xs = QList([1, 2, 3, 4])
+double_xs = xs.map(lambda x: x * 2).collect()
+print(double_xs)
+# [2, 4, 6, 8]
+
+ + +
diff --git a/site/lazy/index.html b/site/lazy/index.html index 1328c16..51e6753 100644 --- a/site/lazy/index.html +++ b/site/lazy/index.html @@ -609,6 +609,7 @@

Lazy

Object representing lazy evaluation of called methods.

Calling any method consumes the current Lazy object. Using the same object again may cause errors due to the draining of the generator.

+

Found in qwlist.Lazy

@@ -858,13 +859,17 @@

Lazy

240 241 242 -243
class Lazy(Generic[T]):
+243
+244
+245
class Lazy(Generic[T]):
     """
     Object representing lazy evaluation of called methods.
 
     Calling any method **consumes** the current `Lazy` object. **Using the same object
     again may cause errors** due to the draining of the generator.
 
+    Found in `qwlist.Lazy`
+
     Examples:
         >>> qlist = QList([1, 2, 3, 4])
         >>> filtered = qlist.filter(lambda x: x < 3)
@@ -1156,12 +1161,12 @@ 

Source code in src\qwlist\qwlist.py -
23
-24
-25
+            
25
 26
 27
-28
def __init__(self, gen: Iterable[T]):
+28
+29
+30
def __init__(self, gen: Iterable[T]):
     """
     Args:
         gen (Iterable[T]): generator used to yield values on collecting items.
@@ -1193,15 +1198,15 @@ 

Source code in src\qwlist\qwlist.py -
156
-157
-158
+            
158
 159
 160
 161
 162
 163
-164
def collect(self):
+164
+165
+166
def collect(self):
     """
     Evaluates the `Lazy` object into `QList`.
     Same as calling `qlist()`
@@ -1245,9 +1250,7 @@ 

Source code in src\qwlist\qwlist.py -
222
-223
-224
+            
224
 225
 226
 227
@@ -1266,7 +1269,9 @@ 

240 241 242 -243

def cycle(self):
+243
+244
+245
def cycle(self):
     """
     Returns a `Lazy[T]` that cycles through the elements of the `Lazy` object, that means
     on achieving the last element the iteration starts from the beginning. The
@@ -1351,9 +1356,7 @@ 

Source code in src\qwlist\qwlist.py -
50
-51
-52
+            
52
 53
 54
 55
@@ -1369,7 +1372,9 @@ 

65 66 67 -68

def filter(self, pred: Callable[[T], bool]):
+68
+69
+70
def filter(self, pred: Callable[[T], bool]):
     """
     Returns a `Lazy` object containing all values from this `Lazy` object for which
     the predicate holds true.
@@ -1450,9 +1455,7 @@ 

Source code in src\qwlist\qwlist.py -
121
-122
-123
+            
123
 124
 125
 126
@@ -1466,7 +1469,9 @@ 

134 135 136 -137

def flatmap(self, mapper: Callable[[T], Iterable[K]]):
+137
+138
+139
def flatmap(self, mapper: Callable[[T], Iterable[K]]):
     """
     Applies the mapper function to each of the yielded elements and flattens the results.
 
@@ -1516,9 +1521,7 @@ 

Source code in src\qwlist\qwlist.py -
206
-207
-208
+            
208
 209
 210
 211
@@ -1530,7 +1533,9 @@ 

217 218 219 -220

def flatten(self) -> "Lazy[T]":
+220
+221
+222
def flatten(self) -> "Lazy[T]":
     """
     If `self` is a `Lazy` object of `Iterable[T]`, flatten concatenates all iterables into a
     single list and returns a `Lazy[T]` object.
@@ -1625,9 +1630,7 @@ 

Source code in src\qwlist\qwlist.py -
 85
- 86
- 87
+            
 87
  88
  89
  90
@@ -1647,7 +1650,9 @@ 

104 105 106 -107

def fold(self, operation: Callable[[K, T], K], init: K) -> K:
+107
+108
+109
def fold(self, operation: Callable[[K, T], K], init: K) -> K:
     """
     Given the combination operator reduces the `Lazy` object by processing
     its constituent parts, building up the final value.
@@ -1725,9 +1730,7 @@ 

Source code in src\qwlist\qwlist.py -
109
-110
-111
+            
111
 112
 113
 114
@@ -1735,7 +1738,9 @@ 

116 117 118 -119

def foreach(self, action: Callable[[T], None]):
+119
+120
+121
def foreach(self, action: Callable[[T], None]):
     """
     Applies the given function to each of yielded elements.
 
@@ -1771,13 +1776,13 @@ 

Source code in src\qwlist\qwlist.py -
33
-34
-35
+            
35
 36
 37
 38
-39
def list(self) -> list[T]:
+39
+40
+41
def list(self) -> list[T]:
     """
     Evaluates the `Lazy` object into `list`.
 
@@ -1840,9 +1845,7 @@ 

Source code in src\qwlist\qwlist.py -
70
-71
-72
+            
72
 73
 74
 75
@@ -1853,7 +1856,9 @@ 

80 81 82 -83

def map(self, mapper: Callable[[T], K]):
+83
+84
+85
def map(self, mapper: Callable[[T], K]):
     """
     Returns a `Lazy` object containing all values from this `Lazy` object with
     the mapping function applied on them.
@@ -1893,14 +1898,14 @@ 

Source code in src\qwlist\qwlist.py -
41
-42
-43
+            
43
 44
 45
 46
 47
-48
def qlist(self):
+48
+49
+50
def qlist(self):
     """
     Evaluates the `Lazy` object into `QList`.
     Same as calling `collect()`
@@ -1942,9 +1947,7 @@ 

Source code in src\qwlist\qwlist.py -
169
-170
-171
+            
171
 172
 173
 174
@@ -1958,7 +1961,9 @@ 

182 183 184 -185

def skip(self, n: int) -> "Lazy[T]":
+185
+186
+187
def skip(self, n: int) -> "Lazy[T]":
     """
     Skips n first elements of the `Lazy` object.
     Args:
@@ -2009,9 +2014,7 @@ 

Source code in src\qwlist\qwlist.py -
187
-188
-189
+            
189
 190
 191
 192
@@ -2026,7 +2029,9 @@ 

201 202 203 -204

def take(self, n: int) -> "Lazy[T]":
+204
+205
+206
def take(self, n: int) -> "Lazy[T]":
     """
     Takes n first elements of the `Lazy` object.
     Args:
@@ -2108,9 +2113,7 @@ 

Source code in src\qwlist\qwlist.py -
139
-140
-141
+            
141
 142
 143
 144
@@ -2123,7 +2126,9 @@ 

151 152 153 -154

def zip(self, other: Iterable[K]) -> "Lazy[tuple[T, K]]":
+154
+155
+156
def zip(self, other: Iterable[K]) -> "Lazy[tuple[T, K]]":
     """
     Combines this `Lazy` object with the given `Iterable` elementwise as tuples.
      The returned `Lazy` objects yields at most the number of elements of
diff --git a/site/qlist/index.html b/site/qlist/index.html
index ce8e822..4ec1289 100644
--- a/site/qlist/index.html
+++ b/site/qlist/index.html
@@ -633,12 +633,14 @@ 

QList

Bases: list

+ +

QList is a python list extension that adds several chainable, lazy +evaluated methods to the standard 'list'.

+

Found in qwlist.QList

Source code in src\qwlist\qwlist.py -
246
-247
-248
+              
248
 249
 250
 251
@@ -902,7 +904,21 @@ 

QList

509 510 511 -512
class QList(list):
+512
+513
+514
+515
+516
+517
+518
+519
+520
class QList(list):
+    """
+    `QList` is a python list extension that adds several chainable, lazy
+    evaluated methods to the standard 'list'.
+
+    Found in `qwlist.QList`
+    """
 
     @overload
     def __getitem__(self, item: slice) -> "QList[T]":
@@ -1213,15 +1229,7 @@ 

Source code in src\qwlist\qwlist.py -
491
-492
-493
-494
-495
-496
-497
-498
-499
+            
499
 500
 501
 502
@@ -1234,7 +1242,15 @@ 

509 510 511 -512

def cycle(self):
+512
+513
+514
+515
+516
+517
+518
+519
+520
def cycle(self):
     """
     Returns a Lazy[T] that cycles through the elements of the QList that means
     on achieving the last element the iteration starts from the beginning. The
@@ -1281,14 +1297,14 @@ 

Source code in src\qwlist\qwlist.py -
286
-287
-288
-289
-290
-291
-292
-293
def eager(self) -> "EagerQList[T]":
+            
294
+295
+296
+297
+298
+299
+300
+301
def eager(self) -> "EagerQList[T]":
     """
     Changes QList into EagerQList.
 
@@ -1352,20 +1368,20 @@ 

Source code in src\qwlist\qwlist.py -
295
-296
-297
-298
-299
-300
-301
-302
-303
+            
303
 304
 305
 306
 307
-308
def filter(self, pred: Callable[[T], bool]) -> Lazy[T]:
+308
+309
+310
+311
+312
+313
+314
+315
+316
def filter(self, pred: Callable[[T], bool]) -> Lazy[T]:
     """
     Returns a Lazy object containing all values from the QList for which
     the predicate holds true.
@@ -1441,15 +1457,7 @@ 

Source code in src\qwlist\qwlist.py -
395
-396
-397
-398
-399
-400
-401
-402
-403
+            
403
 404
 405
 406
@@ -1457,7 +1465,15 @@ 

408 409 410 -411

def flatmap(self, mapper: Callable[[T], Iterable[K]]) -> Lazy[K]:
+411
+412
+413
+414
+415
+416
+417
+418
+419
def flatmap(self, mapper: Callable[[T], Iterable[K]]) -> Lazy[K]:
     """
     Applies the mapper function to each element of the QList and flattens the results.
 
@@ -1500,16 +1516,16 @@ 

Source code in src\qwlist\qwlist.py -
480
-481
-482
-483
-484
-485
-486
-487
-488
-489
def flatten(self) -> Lazy[T]:
+            
488
+489
+490
+491
+492
+493
+494
+495
+496
+497
def flatten(self) -> Lazy[T]:
     """
     If self is a QList of Iterable[T] flatten concatenates all iterables into a
     single list and returns a Lazy[T] object
@@ -1600,15 +1616,7 @@ 

Source code in src\qwlist\qwlist.py -
337
-338
-339
-340
-341
-342
-343
-344
-345
+            
345
 346
 347
 348
@@ -1623,7 +1631,15 @@ 

357 358 359 -360

def fold(self, operation: Callable[[K, T], K], init: K) -> K:
+360
+361
+362
+363
+364
+365
+366
+367
+368
def fold(self, operation: Callable[[K, T], K], init: K) -> K:
     """
     Given the combination operator reduces the QList by processing
     its values, building up the final value.
@@ -1727,15 +1743,7 @@ 

Source code in src\qwlist\qwlist.py -
362
-363
-364
-365
-366
-367
-368
-369
-370
+            
370
 371
 372
 373
@@ -1748,7 +1756,15 @@ 

380 381 382 -383

def fold_right(self, operation: Callable[[K, T], K], init: K) -> K:
+383
+384
+385
+386
+387
+388
+389
+390
+391
def fold_right(self, operation: Callable[[K, T], K], init: K) -> K:
     """
     Given the combination operator reduces the QList by processing
     its values, building up the final value.
@@ -1825,17 +1841,17 @@ 

Source code in src\qwlist\qwlist.py -
325
-326
-327
-328
-329
-330
-331
-332
-333
+            
333
 334
-335
def foreach(self, action: Callable[[T], None]):
+335
+336
+337
+338
+339
+340
+341
+342
+343
def foreach(self, action: Callable[[T], None]):
     """
     Applies the given function to each of the QList elements.
 
@@ -1872,15 +1888,15 @@ 

Source code in src\qwlist\qwlist.py -
385
-386
-387
-388
-389
-390
-391
-392
-393
def len(self) -> int:
+            
393
+394
+395
+396
+397
+398
+399
+400
+401
def len(self) -> int:
     """
     Returns the len of the QList
 
@@ -1914,13 +1930,13 @@ 

Source code in src\qwlist\qwlist.py -
278
-279
-280
-281
-282
-283
-284
def list(self) -> list[T]:
+            
286
+287
+288
+289
+290
+291
+292
def list(self) -> list[T]:
     """
     Changes QList into list.
 
@@ -1983,20 +1999,20 @@ 

Source code in src\qwlist\qwlist.py -
310
-311
-312
-313
-314
-315
-316
-317
-318
+            
318
 319
 320
 321
 322
-323
def map(self, mapper: Callable[[T], K]) -> Lazy[K]:
+323
+324
+325
+326
+327
+328
+329
+330
+331
def map(self, mapper: Callable[[T], K]) -> Lazy[K]:
     """
     Returns a Lazy object containing all values from QList with
     the mapping function applied on them.
@@ -2076,15 +2092,7 @@ 

Source code in src\qwlist\qwlist.py -
441
-442
-443
-444
-445
-446
-447
-448
-449
+            
449
 450
 451
 452
@@ -2093,7 +2101,15 @@ 

455 456 457 -458

def skip(self, n: int) -> Lazy[T]:
+458
+459
+460
+461
+462
+463
+464
+465
+466
def skip(self, n: int) -> Lazy[T]:
     """
     Skips n first elements of the QList.
 
@@ -2167,22 +2183,22 @@ 

Source code in src\qwlist\qwlist.py -
261
-262
-263
-264
-265
-266
-267
-268
-269
+            
269
 270
 271
 272
 273
 274
 275
-276
def slice(self, s: slice) -> Lazy[T]:
+276
+277
+278
+279
+280
+281
+282
+283
+284
def slice(self, s: slice) -> Lazy[T]:
     """
     Calling this method with `slice(3)` works similarly to
     `list[:3]` but is lazy evaluated.
@@ -2269,20 +2285,20 @@ 

Source code in src\qwlist\qwlist.py -
426
-427
-428
-429
-430
-431
-432
-433
-434
+            
434
 435
 436
 437
 438
-439
def sorted(self, key: Callable[[T], SupportsLessThan] = None, reverse: bool = False) -> "QList[T]":
+439
+440
+441
+442
+443
+444
+445
+446
+447
def sorted(self, key: Callable[[T], SupportsLessThan] = None, reverse: bool = False) -> "QList[T]":
     """
     Returns a new QList containing all items from the original list in ascending order.
 
@@ -2358,15 +2374,7 @@ 

Source code in src\qwlist\qwlist.py -
460
-461
-462
-463
-464
-465
-466
-467
-468
+            
468
 469
 470
 471
@@ -2376,7 +2384,15 @@ 

475 476 477 -478

def take(self, n: int) -> Lazy[T]:
+478
+479
+480
+481
+482
+483
+484
+485
+486
def take(self, n: int) -> Lazy[T]:
     """
     Takes n first elements of the QList.
 
@@ -2452,18 +2468,18 @@ 

Source code in src\qwlist\qwlist.py -
413
-414
-415
-416
-417
-418
-419
-420
-421
+            
421
 422
 423
-424
def zip(self, other: Iterable[K]) -> Lazy[tuple[T, K]]:
+424
+425
+426
+427
+428
+429
+430
+431
+432
def zip(self, other: Iterable[K]) -> Lazy[tuple[T, K]]:
     """
     Combines this QList with the given Iterable elementwise as tuples.
      The returned Lazy objects yields at most the number of elements of
diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz
index ebfebc4178c04fac2e1051673304865d4a477d66..fb5f1b921cca30bc4b4a3cb1f3e6f5f88e258ebd 100644
GIT binary patch
delta 12
Tcmb=gXOr*d;CS|IB3mT@8`cDy

delta 12
Tcmb=gXOr*d;K;i+k*yK{89oFP

diff --git a/src/qwlist/qwlist.py b/src/qwlist/qwlist.py
index 17a0fff..8e1ad92 100644
--- a/src/qwlist/qwlist.py
+++ b/src/qwlist/qwlist.py
@@ -12,6 +12,8 @@ class Lazy(Generic[T]):
     Calling any method **consumes** the current `Lazy` object. **Using the same object
     again may cause errors** due to the draining of the generator.
 
+    Found in `qwlist.Lazy`
+
     Examples:
         >>> qlist = QList([1, 2, 3, 4])
         >>> filtered = qlist.filter(lambda x: x < 3)
@@ -244,6 +246,12 @@ def inner():
 
 
 class QList(list):
+    """
+    `QList` is a python list extension that adds several chainable, lazy
+    evaluated methods to the standard 'list'.
+
+    Found in `qwlist.QList`
+    """
 
     @overload
     def __getitem__(self, item: slice) -> "QList[T]":