1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2019 Louis-Vincent Boudreault <lv.boudreault95@gmail.com>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # This modules provides a new functional interface for `Iterator`.
20 import functional_types
25 # Sorts an array with a function.
32 # def get_name(p: Person) do return p.name
34 # var ps = [new Person("Turing"), new Person("Curry"), new Person("Alfredo")]
35 # ps.sort_with(&get_name)
36 # assert ps[0].name == "Alfredo"
37 # assert ps[1].name == "Curry"
38 # assert ps[2].name == "Turing"
40 fun sort_with
(f
: Fun1[E
, Comparable])
42 var cmp
= new ComparatorWith[E
](f
)
44 cmp
.quick_sort
(self, 0, length
- 1)
49 redef interface Iterator[E
]
51 # Applies a function to every elements
54 # fun add(x: Int): Int do return x + 1
57 # var xs = [1,2,3,4,5]
58 # var actual = xs.iterator.map(f).to_a
59 # assert actual == [2,3,4,5,6]
61 fun map
(f
: Fun1[E
,Object]): MapIter[E
,Object]
63 return new MapIter[E
,Object](self, f
)
66 # Iterator that gives the current count and element as a pair
67 fun enumerate
: EnumerateIter[E
]
69 return new EnumerateIter[E
](self)
72 # Iterator that filters elements by a predicate
75 # fun lt10(x: Int): Bool do return x < 10
79 # var actual = xs.iterator.filter(pred).to_a
80 # assert actual == [1..9].to_a
82 fun filter
(pred
: Fun1[E
,Bool]): FilterIter[E
]
84 return new FilterIter[E
](self,pred
)
87 # Checks if at least one element respects a predicate
90 # fun eq10(x: Int): Bool do return x == 10
93 # var xs = [1,2,5,7,9,10,44]
94 # assert xs.iterator.any(pred)
96 # assert not ys.iterator.any(pred)
97 # assert not [1,2,44].iterator.any(pred)
99 fun any
(pred
: Fun1[E
,Bool]): Bool
109 # Checks if all elements respect a predicate
112 # fun lt10(x: Int): Bool do return x < 10
116 # assert xs.iterator.all(pred)
117 # assert [].iterator.all(pred)
118 # assert not [1..10].iterator.all(pred)
120 fun all
(pred
: Fun1[E
,Bool]): Bool
123 if not pred
.call
(x
) then
130 # Folds an iterator from the left
133 # fun adder(x: Int, y: Int): Int do return x + y
136 # assert xs.iterator.fold(0, &adder) == 55
138 fun fold
(acc
: Object, f
: Fun2[Object, E
, Object]): Object
146 # Folds and apply two element at a time
149 # fun min_int(x: Int, y: Int): Int
151 # if x < y then return x
155 # var xs = [100,423,51,1,-19,55,999,-18]
156 # assert xs.iterator.fold1(&min_int) == -19
158 # REQUIRE : length > 1
159 fun fold1
(f
: Fun2[E
,E
,E
]): E
165 var res
= f
.call
(a1
,a2
)
172 # Apply a mutation function over all elements
183 # var ps = [new Persone(1), new Person(2), new Person(3)]
184 # var ages = ps.iterator.for_each(&Person::incr_age).map(&Person::age).to_a
185 # assert ages == [2,3,4]
187 fun for_each
(f
: Proc1[E
])
194 # Maps every element to a nested structure then flattens it
197 # fun chars_fn(s: String): Iterator[Char]
199 # return s.chars.iterator
201 # var cs = ["aaa","bbb","ccc"]
202 # assert cs.iterator.flat_map(&chars_fn).to_a.join == "aaabbbccc"
204 fun flat_map
(f
: Fun1[E
, Iterator[Object]]): FlatMapIter[E
, Object]
206 return new FlatMapIter[E
, Object](self, f
)
209 # Generates an `Iterator` whose elements are sorted by the function
210 # passed in argument.
217 # def get_name(p: Person) do return p.name
219 # var ps = [new Person("Turing"), new Person("Curry"), new Person("Alfredo")]
220 # var ordered_names = ps.iterator.order_by(&get_name).map(&get_name).to_a
221 # assert ordered_names == ["Alfredo", "Curry", "Turing"]
223 fun order_by
(f
: Fun1[E
, Comparable]): OrderedIter[E
]
225 return new OrderedIter[E
](self, f
)
230 # Base class for all iterators using functional types.
231 private abstract class FunIter[OLD,NEW]
233 var my_iter
: Iterator[OLD]
256 # An iterator that maps each item with `f`.
263 return f
.call
(my_iter
.item
)
268 # An iterator that maps each item to a pair containing the item with its
270 class EnumerateIter[E
]
271 super FunIter[E
, Pair[Int,E
]]
275 return new Pair[Int,E
](0, my_iter
.item
)
279 # An tierator that filter its element by a predicate `pred`.
281 super FunIter[E
,nullable E
]
282 var pred
: Fun1[E
, Bool]
286 if is_ok
and not pred
.call
(my_iter
.item
) then next
310 # An iterator that maps each item to an iterator and yield
312 class FlatMapIter[A
,B
]
314 var f
: Fun1[A
, Iterator[B
]]
315 protected var inner
: nullable Iterator[B
] = null
324 return inner
.as(not null).item
335 if not inner
.is_ok
then
341 # Tries to resolve the inner iterator.
342 # Assigns null to `inner` if it fails.
343 protected fun try_compute_inner
346 if not my_iter
.is_ok
then return
347 var res
= f
.call
(my_iter
.item
)
348 if res
.is_ok
then inner
= res
352 # An iterator that yield each item in order
355 var f
: Fun1[E
, Comparable]
357 private var sorted_iter
: Iterator[E
] is noinit
358 private var sorted_arr
: Array[E
] is noinit
362 sorted_arr
= my_iter
.to_a
363 sorted_arr
.sort_with
(f
)
364 sorted_iter
= sorted_arr
.iterator
374 return sorted_iter
.item
379 return sorted_iter
.is_ok
393 # Comparator that use a function provided by the user to compare between elements.
394 class ComparatorWith[E
]
396 redef type COMPARED: E
398 var f
: Fun1[E
, Comparable]
400 redef fun compare
(a
,b
)
404 if x
< y
then return -1
405 if x
> y
then return 1