Skip to content

Commit a5e1e24

Browse files
author
czheo
committed
add stream
1 parent 372cc95 commit a5e1e24

File tree

5 files changed

+80
-4
lines changed

5 files changed

+80
-4
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,19 @@ def push(lst, x):
184184
# returns [1,2,3]
185185
```
186186

187+
### stream
188+
189+
``` python
190+
from syntax_sugar import stream, take
191+
192+
list(stream() << [1,2,3] << range(5))
193+
# [1,2,3,0,1,2,3,4]
194+
# stream will connect all sequences together
195+
196+
list((stream() << [1, 1] << (lambda x, y: x + y)) /take/ 10)
197+
# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
198+
# This is the first 10 items of an infinite fibonacci stream
199+
# If a function is met, it will infinitely take the last N previous items to generate the next item.
200+
```
201+
187202
More receipes: https://github.com/czheo/syntax_sugar_python/tree/master/recipes

syntax_sugar/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from .composable import *
33
from .pipe import *
44
from .infix import *
5+
from .stream import *

syntax_sugar/composable.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
]
99

1010
class composable(partial):
11-
def __mul__(self, func):
12-
return lambda *args, **kwargs: self(func(*args, **kwargs))
11+
def __mul__(self, rhs):
12+
return lambda *args, **kwargs: self(rhs(*args, **kwargs))
1313

14-
def __rmul__(self, func):
15-
return lambda *args, **kwargs: func(self(*args, **kwargs))
14+
def __rmul__(self, lhs):
15+
return lambda *args, **kwargs: lhs(self(*args, **kwargs))
1616

1717
def compose(*args):
1818
return reduce(lambda acc, fn:

syntax_sugar/stream.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from itertools import chain
2+
from inspect import getfullargspec
3+
4+
__all__ = [
5+
'stream',
6+
]
7+
8+
class StreamIter:
9+
def __init__(self, fn, data):
10+
self.fn = fn
11+
self.fn_argc = len(getfullargspec(fn).args)
12+
self.data = data
13+
self.prev = []
14+
15+
def __iter__(self):
16+
return self
17+
18+
def __next__(self):
19+
try:
20+
ret = next(self.data)
21+
self.prev.append(ret)
22+
while len(self.prev) > self.fn_argc:
23+
self.prev.pop(0)
24+
return ret
25+
except StopIteration:
26+
ret = self.fn(*self.prev)
27+
self.prev.append(ret)
28+
while len(self.prev) > self.fn_argc:
29+
self.prev.pop(0)
30+
return ret
31+
32+
class stream:
33+
def __init__(self, data = None):
34+
if data is None:
35+
self.data = iter([])
36+
else:
37+
self.data = iter(data)
38+
39+
def __iter__(self):
40+
return self
41+
42+
def __next__(self):
43+
return next(self.data)
44+
45+
def __lshift__(self, rhs):
46+
if hasattr(rhs, '__iter__'):
47+
self.data = chain(self.data, rhs)
48+
elif hasattr(rhs, '__call__'):
49+
self.data = StreamIter(rhs, self.data)
50+
return self

tests/test_stream.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from syntax_sugar import *
2+
3+
def test_stream_collection():
4+
assert list(stream() << [1,2,3] << [4,5,6]) == list([1,2,3,4,5,6])
5+
assert list(stream() << [1,2,3] << range(4,7)) == list([1,2,3,4,5,6])
6+
7+
def test_stream_function():
8+
assert list((stream() << [1,2,3] << (lambda x: x+1)) /take/ 5) == list([1,2,3,4,5])
9+
assert list((stream() << [1,2,3] << (lambda x: x+1)) /drop/ 3 /take/ 5) == list([4,5,6,7,8])
10+
assert list((stream() << range(1,10) << (lambda x: x+1)) /drop/ 3 /take/ 5) == list([4,5,6,7,8])

0 commit comments

Comments
 (0)