@@ -998,7 +998,7 @@ The following recipes have a more mathematical flavor:
998998
999999 def sum_of_squares(it):
10001000 "Add up the squares of the input values."
1001- # sum_of_squares([10, 20, 30]) -> 1400
1001+ # sum_of_squares([10, 20, 30]) -- > 1400
10021002 return math.sumprod(*tee(it))
10031003
10041004 def reshape(matrix, cols):
@@ -1019,17 +1019,16 @@ The following recipes have a more mathematical flavor:
10191019
10201020 def convolve(signal, kernel):
10211021 """Discrete linear convolution of two iterables.
1022+ Equivalent to polynomial multiplication.
10221023
1023- The kernel is fully consumed before the calculations begin.
1024- The signal is consumed lazily and can be infinite.
1025-
1026- Convolutions are mathematically commutative.
1027- If the signal and kernel are swapped,
1028- the output will be the same.
1024+ Convolutions are mathematically commutative; however, the inputs are
1025+ evaluated differently. The signal is consumed lazily and can be
1026+ infinite. The kernel is fully consumed before the calculations begin.
10291027
10301028 Article: https://betterexplained.com/articles/intuitive-convolution/
10311029 Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
10321030 """
1031+ # convolve([1, -1, -20], [1, -3]) --> 1 -4 -17 60
10331032 # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
10341033 # convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
10351034 # convolve(data, [1, -2, 1]) --> 2nd derivative estimate
@@ -1067,7 +1066,7 @@ The following recipes have a more mathematical flavor:
10671066 f(x) = x³ -4x² -17x + 60
10681067 f'(x) = 3x² -8x -17
10691068 """
1070- # polynomial_derivative([1, -4, -17, 60]) -> [3, -8, -17]
1069+ # polynomial_derivative([1, -4, -17, 60]) -- > [3, -8, -17]
10711070 n = len(coefficients)
10721071 powers = reversed(range(1, n))
10731072 return list(map(operator.mul, coefficients, powers))
@@ -1169,6 +1168,12 @@ The following recipes have a more mathematical flavor:
11691168
11701169 >>> take(10 , count())
11711170 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1171+ >>> # Verify that the input is consumed lazily
1172+ >>> it = iter (' abcdef' )
1173+ >>> take(3 , it)
1174+ ['a', 'b', 'c']
1175+ >>> list (it)
1176+ ['d', 'e', 'f']
11721177
11731178 >>> list (prepend(1 , [2 , 3 , 4 ]))
11741179 [1, 2, 3, 4]
@@ -1181,25 +1186,45 @@ The following recipes have a more mathematical flavor:
11811186
11821187 >>> list (tail(3 , ' ABCDEFG' ))
11831188 ['E', 'F', 'G']
1189+ >>> # Verify the input is consumed greedily
1190+ >>> input_iterator = iter (' ABCDEFG' )
1191+ >>> output_iterator = tail(3 , input_iterator)
1192+ >>> list (input_iterator)
1193+ []
11841194
11851195 >>> it = iter (range (10 ))
11861196 >>> consume(it, 3 )
1197+ >>> # Verify the input is consumed lazily
11871198 >>> next (it)
11881199 3
1200+ >>> # Verify the input is consumed completely
11891201 >>> consume(it)
11901202 >>> next (it, ' Done' )
11911203 'Done'
11921204
11931205 >>> nth(' abcde' , 3 )
11941206 'd'
1195-
11961207 >>> nth(' abcde' , 9 ) is None
11971208 True
1209+ >>> # Verify that the input is consumed lazily
1210+ >>> it = iter (' abcde' )
1211+ >>> nth(it, 2 )
1212+ 'c'
1213+ >>> list (it)
1214+ ['d', 'e']
11981215
11991216 >>> [all_equal(s) for s in (' ' , ' A' , ' AAAA' , ' AAAB' , ' AAABA' )]
12001217 [True, True, True, False, False]
12011218 >>> [all_equal(s, key = str .casefold) for s in (' ' , ' A' , ' AaAa' , ' AAAB' , ' AAABA' )]
12021219 [True, True, True, False, False]
1220+ >>> # Verify that the input is consumed lazily and that only
1221+ >>> # one element of a second equivalence class is used to disprove
1222+ >>> # the assertion that all elements are equal.
1223+ >>> it = iter (' aaabbbccc' )
1224+ >>> all_equal(it)
1225+ False
1226+ >>> ' ' .join(it)
1227+ 'bbccc'
12031228
12041229 >>> quantify(range (99 ), lambda x : x% 2 == 0 )
12051230 50
@@ -1222,6 +1247,11 @@ The following recipes have a more mathematical flavor:
12221247
12231248 >>> list (ncycles(' abc' , 3 ))
12241249 ['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']
1250+ >>> # Verify greedy consumption of input iterator
1251+ >>> input_iterator = iter (' abc' )
1252+ >>> output_iterator = ncycles(input_iterator, 3 )
1253+ >>> list (input_iterator)
1254+ []
12251255
12261256 >>> sum_of_squares([10 , 20 , 30 ])
12271257 1400
@@ -1248,19 +1278,41 @@ The following recipes have a more mathematical flavor:
12481278
12491279 >>> list (transpose([(1 , 2 , 3 ), (11 , 22 , 33 )]))
12501280 [(1, 11), (2, 22), (3, 33)]
1281+ >>> # Verify that the inputs are consumed lazily
1282+ >>> input1 = iter ([1 , 2 , 3 ])
1283+ >>> input2 = iter ([11 , 22 , 33 ])
1284+ >>> output_iterator = transpose([input1, input2])
1285+ >>> next (output_iterator)
1286+ (1, 11)
1287+ >>> list (zip (input1, input2))
1288+ [(2, 22), (3, 33)]
12511289
12521290 >>> list (matmul([(7 , 5 ), (3 , 5 )], [[2 , 5 ], [7 , 9 ]]))
12531291 [(49, 80), (41, 60)]
12541292 >>> list (matmul([[2 , 5 ], [7 , 9 ], [3 , 4 ]], [[7 , 11 , 5 , 4 , 9 ], [3 , 5 , 2 , 6 , 3 ]]))
12551293 [(29, 47, 20, 38, 33), (76, 122, 53, 82, 90), (33, 53, 23, 36, 39)]
12561294
1295+ >>> list (convolve([1 , - 1 , - 20 ], [1 , - 3 ])) == [1 , - 4 , - 17 , 60 ]
1296+ True
12571297 >>> data = [20 , 40 , 24 , 32 , 20 , 28 , 16 ]
12581298 >>> list (convolve(data, [0.25 , 0.25 , 0.25 , 0.25 ]))
12591299 [5.0, 15.0, 21.0, 29.0, 29.0, 26.0, 24.0, 16.0, 11.0, 4.0]
12601300 >>> list (convolve(data, [1 , - 1 ]))
12611301 [20, 20, -16, 8, -12, 8, -12, -16]
12621302 >>> list (convolve(data, [1 , - 2 , 1 ]))
12631303 [20, 0, -36, 24, -20, 20, -20, -4, 16]
1304+ >>> # Verify signal is consumed lazily and the kernel greedily
1305+ >>> signal_iterator = iter ([10 , 20 , 30 , 40 , 50 ])
1306+ >>> kernel_iterator = iter ([1 , 2 , 3 ])
1307+ >>> output_iterator = convolve(signal_iterator, kernel_iterator)
1308+ >>> list (kernel_iterator)
1309+ []
1310+ >>> next (output_iterator)
1311+ 10
1312+ >>> next (output_iterator)
1313+ 40
1314+ >>> list (signal_iterator)
1315+ [30, 40, 50]
12641316
12651317 >>> from fractions import Fraction
12661318 >>> from decimal import Decimal
@@ -1348,6 +1400,17 @@ The following recipes have a more mathematical flavor:
13481400 >>> # Test list input. Lists do not support None for the stop argument
13491401 >>> list (iter_index(list (' AABCADEAF' ), ' A' ))
13501402 [0, 1, 4, 7]
1403+ >>> # Verify that input is consumed lazily
1404+ >>> input_iterator = iter (' AABCADEAF' )
1405+ >>> output_iterator = iter_index(input_iterator, ' A' )
1406+ >>> next (output_iterator)
1407+ 0
1408+ >>> next (output_iterator)
1409+ 1
1410+ >>> next (output_iterator)
1411+ 4
1412+ >>> ' ' .join(input_iterator)
1413+ 'DEAF'
13511414
13521415 >>> list (sieve(30 ))
13531416 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
@@ -1499,6 +1562,17 @@ The following recipes have a more mathematical flavor:
14991562 [0, 2, 4, 6, 8]
15001563 >>> list (odds)
15011564 [1, 3, 5, 7, 9]
1565+ >>> # Verify that the input is consumed lazily
1566+ >>> input_iterator = iter (range (10 ))
1567+ >>> evens, odds = partition(is_odd, input_iterator)
1568+ >>> next (odds)
1569+ 1
1570+ >>> next (odds)
1571+ 3
1572+ >>> next (evens)
1573+ 0
1574+ >>> list (input_iterator)
1575+ [4, 5, 6, 7, 8, 9]
15021576
15031577 >>> list (subslices(' ABCD' ))
15041578 ['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
@@ -1518,13 +1592,27 @@ The following recipes have a more mathematical flavor:
15181592 ['A', 'B', 'C', 'D']
15191593 >>> list (unique_everseen(' ABBcCAD' , str .casefold))
15201594 ['A', 'B', 'c', 'D']
1595+ >>> # Verify that the input is consumed lazily
1596+ >>> input_iterator = iter (' AAAABBBCCDAABBB' )
1597+ >>> output_iterator = unique_everseen(input_iterator)
1598+ >>> next (output_iterator)
1599+ 'A'
1600+ >>> ' ' .join(input_iterator)
1601+ 'AAABBBCCDAABBB'
15211602
15221603 >>> list (unique_justseen(' AAAABBBCCDAABBB' ))
15231604 ['A', 'B', 'C', 'D', 'A', 'B']
15241605 >>> list (unique_justseen(' ABBCcAD' , str .casefold))
15251606 ['A', 'B', 'C', 'A', 'D']
15261607 >>> list (unique_justseen(' ABBcCAD' , str .casefold))
15271608 ['A', 'B', 'c', 'A', 'D']
1609+ >>> # Verify that the input is consumed lazily
1610+ >>> input_iterator = iter (' AAAABBBCCDAABBB' )
1611+ >>> output_iterator = unique_justseen(input_iterator)
1612+ >>> next (output_iterator)
1613+ 'A'
1614+ >>> ' ' .join(input_iterator)
1615+ 'AAABBBCCDAABBB'
15281616
15291617 >>> d = dict (a = 1 , b = 2 , c = 3 )
15301618 >>> it = iter_except(d.popitem, KeyError )
@@ -1545,6 +1633,12 @@ The following recipes have a more mathematical flavor:
15451633
15461634 >>> first_true(' ABC0DEF1' , ' 9' , str .isdigit)
15471635 '0'
1636+ >>> # Verify that inputs are consumed lazily
1637+ >>> it = iter (' ABC0DEF1' )
1638+ >>> first_true(it, predicate = str .isdigit)
1639+ '0'
1640+ >>> ' ' .join(it)
1641+ 'DEF1'
15481642
15491643
15501644.. testcode ::
0 commit comments