1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
11 # Service management through the `for` control structure.
13 # The module is a proof-of-concept to investigate the abuse of
14 # the `for` structure to implement various services.
16 # The idea is that, with a `for`, the service-provider can:
17 # * control the end of the service (thus can finalize things
18 # like releasing ressources)
19 # * communicate data with the user on each iteration; the used can
20 # also communicate results to the provider.
23 # Encapsulation of service in a `for`-compatible interface.
25 # The service is not effectively started until the iterate method
26 # is called. Then, each step of the iteration is a step in the service.
28 # While, for a typing point of view, abusers are just classes with an
29 # iterator method, the point of this class is to tag services that return
32 # Note that using having `ForAbuser` as a genuine subclass of `Collection`
33 # works but is not recommended since it may cause mental health issues.
34 interface ForAbuser[E
]
35 # Starts and control the service
36 fun iterator
: Iterator[E
] is abstract
39 # Abuser to read a file, see `file_open`
40 private class ReadFileForAbuser
41 super ForAbuser[FileReader]
43 redef fun iterator
do return new ReadFileForAbuserIterator(path
)
46 # Abuser iterator to read a file, see `file_open`
47 private class ReadFileForAbuserIterator
48 super Iterator[FileReader]
50 redef var item
: FileReader is noinit
51 redef var is_ok
= true
54 # start of service is to open the file, and return in
55 item
= new FileReader.open
(path
)
59 # end of service is to close the file
60 # there is only one iteration
69 # The user is asked to compare `a` with `b` then set `res` accordingly.
71 # * if `a < b` then the user sets `res` to -1
72 # * if `a > b` then the user sets `res` to 1
73 # * if `a == b` then the user sets `res` to 0
75 # It is the responsibility of the user to implement a total order.
76 # ie. the implemented comparison must be asymmetric, transitive and total.
78 # The first element to compare
80 # The second element to compare
82 # The result of the comparison (according to the user)
83 var res
= 0 is writable
86 # Abuser for sorting array, see `sort_fa`
87 private class SortAbuser[E
]
88 super ForAbuser[CompareQuery[E
]]
90 redef fun iterator
do return new SortAbuserIterator[E
](array
)
93 # Abuser iterator for sorting array, see `sort_fa`
94 # Implements a sort by permutation
95 private class SortAbuserIterator[E
]
96 super Iterator[CompareQuery[E
]]
97 # The index of the big loop
99 # The index of the small loop
103 # The query used to communicate with the user.
104 # For ecological concerns, a unique CompareQuery is instatiated.
105 var query
: nullable CompareQuery[E
] = null
106 redef fun item
do return query
.as(not null)
109 # Initialize the algorithm, see `next` for the rest
110 if not is_ok
then return
111 query
= new CompareQuery[E
](array
[i
], array
[j
])
113 redef fun is_ok
do return i
< array
.length
- 1
116 # Process the last query
122 # Get the next iteration
124 if j
>= array
.length
then
129 if not is_ok
then return
130 # Prepare the next query
138 # Sort an array through a `for` abuse.
139 # The user uses the provided query (item) to implements its own comparison
142 # for q in a.sort_fa do q.res = q.a <=> q.b
143 # assert a == [1, 2, 3]
145 # Implements a sort by permutation.
146 fun sort_fa
: ForAbuser[CompareQuery[E
]]
148 return new SortAbuser[E
](self)
154 # Open and read a file through a `for` abuse.
155 # The abuse just ensures that the file is closed after the reading.
157 # for f in file_open("/etc/issue") do
158 # var l = f.read_line
160 # assert not l.is_empty
161 # end # f is automatically closed here
162 fun file_open
(path
: String): ForAbuser[FileReader]
164 return new ReadFileForAbuser(path
)