@@ -5,6 +5,8 @@ defrecord Range, [:first, :last] do
5
5
end
6
6
7
7
defprotocol Range.Iterator do
8
+ def reduce ( first , range , acc , fun )
9
+
8
10
@ doc """
9
11
How to iterate the range, receives the first
10
12
and range as arguments. It needs to return a
@@ -21,6 +23,10 @@ defprotocol Range.Iterator do
21
23
end
22
24
23
25
defimpl Enum.Iterator , for: Range do
26
+ def reduce ( Range [ first : first ] = range , acc , fun ) do
27
+ Range.Iterator . reduce ( first , range , acc , fun )
28
+ end
29
+
24
30
def iterator ( Range [ first : first ] = range ) do
25
31
iterator = Range.Iterator . iterator ( first , range )
26
32
{ iterator , iterator . ( first ) }
@@ -36,6 +42,31 @@ defimpl Enum.Iterator, for: Range do
36
42
end
37
43
38
44
defimpl Range.Iterator , for: Number do
45
+ def reduce ( first , Range [ last : last ] , acc , fun ) when is_integer ( first ) and is_integer ( last ) do
46
+ reducer = if last >= first do
47
+ fn ( acc , fun ) -> do_reducer_up ( first , last , acc , fun ) end
48
+ else
49
+ fn ( acc , fun ) -> do_reducer_down ( first , last , acc , fun ) end
50
+ end
51
+ Enum.Iterator.Function . reduce ( reducer , acc , fun )
52
+ end
53
+
54
+ defp do_reducer_up ( counter , last , acc , fun ) do
55
+ if counter > last do
56
+ acc
57
+ else
58
+ do_reducer_up ( counter + 1 , last , fun . ( counter , acc ) , fun )
59
+ end
60
+ end
61
+
62
+ defp do_reducer_down ( counter , last , acc , fun ) do
63
+ if counter < last do
64
+ acc
65
+ else
66
+ do_reducer_down ( counter - 1 , last , fun . ( counter , acc ) , fun )
67
+ end
68
+ end
69
+
39
70
def iterator ( first , Range [ last : last ] ) when is_integer ( first ) and is_integer ( last ) and last >= first do
40
71
fn ( current ) ->
41
72
if current > last , do: :stop , else: { current , current + 1 }
0 commit comments