1+ defmodule ElixirScript.Enum do
2+
3+ def all? ( enumerable , fun \\ fn ( x ) -> x end ) do
4+ { _ , acc } = Enumerable . reduce ( enumerable , { :cont , true } , fn ( item , _ ) ->
5+ if fun . ( item ) do
6+ { :cont , true }
7+ else
8+ { :halt , false }
9+ end
10+ end )
11+
12+ acc
13+ end
14+
15+ def any? ( enumerable , fun \\ fn ( x ) -> x end ) do
16+ { _ , acc } = Enumerable . reduce ( enumerable , { :cont , true } , fn ( item , _ ) ->
17+ if fun . ( item ) do
18+ { :halt , true }
19+ else
20+ { :cont , false }
21+ end
22+ end )
23+
24+ acc
25+ end
26+
27+ def at ( enumerable , n , default \\ nil ) do
28+ cond do
29+ n > Enumerable . count ( enumerable ) ->
30+ default
31+ true ->
32+ result = Enumerable . reduce ( enumerable , { :cont , 0 } , fn ( item , acc ) ->
33+ if n == acc do
34+ { :halt , item }
35+ else
36+ { :cont , acc + 1 }
37+ end
38+ end )
39+
40+ case result do
41+ { :cont , _ } ->
42+ default
43+ { :halt , item } ->
44+ item
45+ end
46+ end
47+ end
48+
49+ def concat ( [ enumerable ] ) do
50+ enumerable
51+ end
52+
53+ def concat ( [ h | t ] ) do
54+ h . concat ( t )
55+ end
56+
57+ def count ( enumerable ) do
58+ { :ok , num } = Enumerable . count ( enumerable )
59+ num
60+ end
61+
62+ def count ( enumerable , fun ) do
63+ { _ , acc } = Enumerable . reduce ( enumerable , { :cont , 0 } , fn ( item , acc ) ->
64+ if fun . ( item ) do
65+ { :cont , acc + 1 }
66+ else
67+ { :cont , acc }
68+ end
69+ end )
70+
71+ acc
72+ end
73+
74+ def reduce ( enumerable , fun ) do
75+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , nil } , fn
76+ item , nil ->
77+ { :cont , { :acc , item } }
78+ item , { :acc , acc } ->
79+ { :cont , { :acc , fun . ( item , acc ) } }
80+ end )
81+
82+ result
83+ end
84+
85+ def reduce ( enumerable , acc , fun ) do
86+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , acc } , fn
87+ item , acc ->
88+ { :cont , fun . ( item , acc ) }
89+ end )
90+
91+ result
92+ end
93+
94+
95+ def map ( enumerable , fun ) do
96+ reduce ( enumerable , [ ] , fn ( x , acc ) ->
97+ acc ++ fun . ( x )
98+ end )
99+ end
100+
101+ def map_reduce ( enumerable , acc , fun ) do
102+ reduce ( enumerable , { [ ] , acc } , fn ( x , { m , acc } ) ->
103+ { v , new_acc } = fun . ( x , acc )
104+ { m ++ [ v ] , new_acc }
105+ end )
106+ end
107+
108+ def each ( enumerable , fun ) do
109+ map ( enumerable , fun )
110+ :ok
111+ end
112+
113+ def empty? ( enumerable ) do
114+ { :ok , count } = Enumerable . count ( enumerable )
115+ count == 0
116+ end
117+
118+ def fetch ( enumerable , index ) do
119+ result = Enumerable . reduce ( enumerable , { :cont , 0 } , fn ( item , acc ) ->
120+ if index == acc do
121+ { :halt , { :ok , item } }
122+ else
123+ { :cont , acc + 1 }
124+ end
125+ end )
126+
127+ case result do
128+ { :cont , _ } ->
129+ :error
130+ { :halt , item } ->
131+ item
132+ end
133+ end
134+
135+ def fetch! ( enumerable , index ) do
136+ case fetch ( enumerable , index ) do
137+ { :ok , item } ->
138+ item
139+ :error ->
140+ raise Enum.OutOfBoundsError
141+ end
142+ end
143+
144+ def filter ( enumerable , fun ) do
145+ reduce ( enumerable , [ ] , fn ( x , acc ) ->
146+ if fun . ( x ) do
147+ acc ++ [ x ]
148+ else
149+ acc
150+ end
151+ end )
152+ end
153+
154+ def filter_map ( enumerable , filter , mapper ) do
155+ reduce ( enumerable , [ ] , fn ( x , acc ) ->
156+ if filter . ( x ) do
157+ acc ++ [ mapper . ( x ) ]
158+ else
159+ acc
160+ end
161+ end )
162+ end
163+
164+ def find ( enumerable , default \\ nil , fun ) do
165+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , default } , fn ( item , acc ) ->
166+ if fun . ( item ) do
167+ { :halt , item }
168+ else
169+ { :cont , default }
170+ end
171+ end )
172+
173+ result
174+ end
175+
176+ def member? ( enumerable , value ) do
177+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , false } , fn ( item , acc ) ->
178+ if item == value do
179+ { :halt , true }
180+ else
181+ { :cont , false }
182+ end
183+ end )
184+
185+ result
186+ end
187+
188+ def drop ( enumerable , count ) do
189+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , { [ ] , 0 } } , fn
190+ ( item , { taken , drop_count } ) ->
191+ if drop_count < count do
192+ { :cont , { [ ] , drop_count + 1 } }
193+ else
194+ { :cont , taken ++ [ item ] }
195+ end
196+ end )
197+
198+ result
199+ end
200+
201+ def drop_while ( enumerable , fun ) do
202+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , [ ] } , fn
203+ ( item , taken ) ->
204+ if fun . ( item ) do
205+ { :cont , { taken } }
206+ else
207+ { :cont , taken ++ [ item ] }
208+ end
209+ end )
210+
211+ result
212+ end
213+
214+
215+ def take ( enumerable , count ) do
216+ if Enumerable . count ( enumerable ) < count do
217+ enumerable
218+ else
219+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , { [ ] , 0 } } , fn
220+ ( item , { taken , taken_count } ) ->
221+ if taken_count == count do
222+ { :halt , taken }
223+ else
224+ { :cont , { taken ++ [ item ] , taken_count + 1 } }
225+ end
226+ end )
227+
228+ result
229+ end
230+ end
231+
232+ def take_every ( enumerable , nth ) do
233+ { _ , { result , _count } } = Enumerable . reduce ( enumerable , { :cont , { [ ] , 0 } } , fn
234+ ( item , { taken , count } ) ->
235+ if rem ( count , nth ) == 0 do
236+ { :cont , { taken ++ [ item ] , count + 1 } }
237+ else
238+ { :cont , { taken , count + 1 } }
239+ end
240+ end )
241+
242+ result
243+ end
244+
245+ def take_while ( enumerable , fun ) do
246+ { _ , result } = Enumerable . reduce ( enumerable , { :cont , [ ] } , fn
247+ ( item , taken ) ->
248+ if fun . ( item ) do
249+ { :cont , { taken ++ [ item ] } }
250+ else
251+ { :halt , taken }
252+ end
253+ end )
254+
255+ result
256+ end
257+
258+
259+ def to_list ( enumerable ) when is_list ( enumerable ) do
260+ enumerable
261+ end
262+
263+ def to_list ( enumerable ) do
264+ map ( enumerable , fn x -> x end )
265+ end
266+
267+ def reverse ( enumerable ) when is_list ( enumerable ) do
268+ enumerable . concat ( [ ] ) . reverse ( )
269+ end
270+
271+ def reverse ( enumerable ) do
272+ reduce ( enumerable , [ ] , fn ( item , acc ) ->
273+ [ item ] ++ acc
274+ end )
275+ end
276+
277+ def reverse ( enumerable , tail ) when is_list ( enumerable ) do
278+ enumerable . concat ( [ ] ) . reverse ( ) ++ tail
279+ end
280+
281+ def reverse ( enumerable , tail ) do
282+ result = reduce ( enumerable , [ ] , fn ( item , acc ) ->
283+ [ item ] ++ acc
284+ end )
285+
286+ result ++ tail
287+ end
288+
289+ end
0 commit comments