1- from functools import partial , reduce
2- from itertools import product , islice
3- from .util import flip
4- from .composable import compose
1+ from functools import partial
2+ from .iter import Iterator , Range
3+
4+ __all__ = [
5+ 'infix' ,
6+ 'is_a' ,
7+ 'to' ,
8+ 'by' ,
9+ 'INF' ,
10+ 'NEGINF' ,
11+ 'hasattr' ,
12+ 'take' ,
13+ 'drop' ,
14+ ]
15+
16+ INF = float ('inf' )
17+ NEGINF = float ('-inf' )
518
619class infix (partial ):
720 def __truediv__ (self , right ):
@@ -10,130 +23,32 @@ def __truediv__(self, right):
1023 def __rtruediv__ (self , left ):
1124 return infix (self .func , left )
1225
13- is_a = of = infix (isinstance )
14- contains = infix (lambda lst , item : item in lst )
15- pair = infix (lambda a , b : (a , b ))
16- join = infix (lambda lst , s : s .join (lst ))
26+ is_a = infix (isinstance )
1727hasattr = infix (hasattr )
18- fmap = infix (flip (map ))
19- ffilter = infix (flip (filter ))
20- freduce = infix (flip (reduce ))
21- take = infix (compose (list , islice ))
22- drop = infix (lambda seq , idx : islice (seq , idx , None ))
23-
24- INF = float ('inf' )
25- NEGINF = float ('-inf' )
26-
27- class To :
28- def __init__ (self , start , end ):
29- if start in {INF , NEGINF }:
30- raise ValueError ('Cannot start range from infinity' )
31-
32- valid_char = lambda c : c / of / str and len (c ) == 1
33- valid_integer = lambda i : i / of / int or i == INF or i == NEGINF
34-
35- if valid_integer (start ) and valid_integer (end ):
36- self .type = 'number'
37- elif valid_char (start ) and valid_char (end ):
38- self .type = 'char'
39- else :
40- raise TypeError ('Unknown range: %s to %s' % (start , end ))
41-
42- self .start = start
43- self .curr = self .start
44- self ._step = 1 if end > start else - 1
45- self .end = end
46-
47- @property
48- def step (self ):
49- return self ._step
50-
51- @step .setter
52- def step (self , value ):
53- if not value / is_a / int :
54- raise TypeError ('Step must be int' )
55- elif value == 0 :
56- raise ValueError ('Step cannot be zero' )
57- elif self .start < self .end and value < 0 :
58- raise ValueError ('Increasing range with negative step' )
59- elif self .start > self .end and value > 0 :
60- raise ValueError ('Decreasing range with positive step' )
61-
62- self ._step = value
63-
64- def __mul__ (self , rhs ):
65- return product (self , rhs )
66-
67- def __iter__ (self ):
68- return self
69-
70- def __next__ (self ):
71- def next_number ():
72- too_big = self .step > 0 and self .curr > self .end
73- too_small = self .step < 0 and self .curr < self .end
74-
75- if too_big or too_small : raise StopIteration
76-
77- ret = self .curr
78- self .curr += self .step
79- return ret
80-
81- def next_char ():
82- too_big = self .step > 0 and ord (self .curr ) > ord (self .end )
83- too_small = self .step < 0 and ord (self .curr ) < ord (self .end )
84-
85- if too_big or too_small : raise StopIteration
86-
87- ret = self .curr
88- self .curr = chr (ord (self .curr ) + self .step )
89- return ret
90-
91- if self .type == 'number' :
92- return next_number ()
93- elif self .type == 'char' :
94- return next_char ()
95- else :
96- raise StopIteration
97-
98- def __str__ (self ):
99- if self .type == 'number' :
100- return super (To , self ).__str__ ()
101- elif self .type == 'char' :
102- return '' .join (self )
103- else :
104- raise NotImplementedError
10528
10629@infix
10730def to (start , end ):
108- return To ( start , end )
31+ return Iterator ( Range ( start , end ) )
10932
11033@infix
111- def by (to_object , step ):
112- if to_object .end >= to_object .start and step < 0 :
113- to_object .step = - step
114- elif to_object .end <= to_object .start and step > 0 :
115- to_object .step = - step
116- else :
117- to_object .step = step
118-
119- return to_object
34+ def by (obj , step ):
35+ # ex. -2 step -> 2 step
36+ step = abs (step )
37+ obj = Iterator (obj ) if not obj / is_a / Iterator else obj
38+ return obj .slice (step = step )
12039
40+ @infix
41+ def take (obj , n ):
42+ # ex. n = 3
43+ # [0, 1, 2, 3, 4, 5, 6] =>
44+ # [0, 1, 2]
45+ obj = Iterator (obj ) if not obj / is_a / Iterator else obj
46+ return obj .slice (stop = n )
12147
122- __all__ = [
123- 'infix' ,
124- 'of' ,
125- 'is_a' ,
126- 'contains' ,
127- 'pair' ,
128- 'join' ,
129- 'to' ,
130- 'by' ,
131- 'INF' ,
132- 'NEGINF' ,
133- 'hasattr' ,
134- 'fmap' ,
135- 'freduce' ,
136- 'ffilter' ,
137- 'take' ,
138- 'drop' ,
139- ]
48+ @infix
49+ def drop (obj , n ):
50+ # ex. n = 3
51+ # [0, 1, 2, 3, 4, 5, 6] =>
52+ # [3, 4, 5, 6]
53+ obj = Iterator (obj ) if not obj / is_a / Iterator else obj
54+ return obj .slice (start = n )
0 commit comments