--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT. This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+# Service management trough the `for` control structure.
+#
+# The module is a proof-of-concept to investigate the abuse of
+# the `for` structure to implement various services.
+#
+# The idea is that, with a `for`, the service-provider can:
+# * control the end of the service (thus can finalize things
+# like releasing ressources)
+# * communicate data with the user on each iteration; the used can
+# also communicate results to the provider.
+module for_abuse
+
+# Encapsulation of service in a `for`-compatible interface.
+#
+# The service is not effectively started until the iterate method
+# is called. Then, each step of the iteration is a step in the service.
+#
+# While, for a typing point of view, abusers are just collections,
+# the point of this class is to tag services that return a ForAbuser
+# object.
+# Note that using abuser as genuine collection should work but is not
+# recommended since it may cause mental health issues.
+interface ForAbuser[E]
+ super Collection[E]
+end
+
+# Abuser to read a file, see `file_open`
+private class ReadFileForAbuser
+ super ForAbuser[IFStream]
+ var path: String
+ redef fun iterator do return new ReadFileForAbuserIterator(path)
+end
+
+# Abuser iterator to read a file, see `file_open`
+private class ReadFileForAbuserIterator
+ super Iterator[IFStream]
+ redef var item: IFStream
+ redef var is_ok = true
+ init(path: String)
+ do
+ # start of service is to open the file, and return in
+ item = new IFStream.open(path)
+ end
+ redef fun next
+ do
+ # end of service is to close the file
+ # there is only one iteration
+ is_ok = false
+ item.close
+ end
+end
+
+####
+
+# A comparison query.
+# The user is asked to compare `a` with `b` then set `res` accordingly.
+#
+# * if `a < b` then the user sets `res` to -1
+# * if `a > b` then the user sets `res` to 1
+# * if `a == b` then the user sets `res` to 0
+#
+# It is the responsibility of the user to implement a total order.
+# ie. the implemented comparison must be asymmetric, transitive and total.
+class CompareQuery[E]
+ # The first element to compare
+ var a: E
+ # The second element to compare
+ var b: E
+ # The result of the comparison (according to the user)
+ var res writable = 0
+end
+
+# Abuser for sorting array, see `sort_fa`
+private class SortAbuser[E]
+ super ForAbuser[CompareQuery[E]]
+ var array: Array[E]
+ redef fun iterator do return new SortAbuserIterator[E](array)
+end
+
+# Abuser iterator for sorting array, see `sort_fa`
+# Implements a sort by permutation
+private class SortAbuserIterator[E]
+ super Iterator[CompareQuery[E]]
+ # The index of the big loop
+ var i: Int
+ # The index of the small loop
+ var j: Int
+ # The array to sort
+ var array: Array[E]
+ # The query used to communicate with the user.
+ # For ecological concerns, a unique CompareQuery is instatiated.
+ var query: nullable CompareQuery[E]
+ redef fun item do return query.as(not null)
+ init(array: Array[E])
+ do
+ self.array = array
+ # Initialize the algorithm, see `next` for the rest
+ i = 0
+ j = 0
+ if not is_ok then return
+ query = new CompareQuery[E](array[i], array[j])
+ end
+ redef fun is_ok do return i < array.length - 1
+ redef fun next
+ do
+ # Process the last query
+ if item.res > 0 then
+ var tmp = array[i]
+ array[i] = array[j]
+ array[j] = tmp
+ end
+ # Get the next iteration
+ j += 1
+ if j >= array.length then
+ # End of small loop
+ i += 1
+ j = i + 1
+ end
+ if not is_ok then return
+ # Prepare the next query
+ item.a = array[i]
+ item.b = array[j]
+ item.res = 0
+ end
+end
+
+redef class Array[E]
+ # Sort an array trough a `for` abuse.
+ # The user uses the provided query (item) to implements its own comparison
+ #
+ # var a = [1, 3, 2]
+ # for q in a do q.res = q.a <=> q.b
+ # print a # => 123
+ #
+ # Implements a sort by permutation.
+ fun sort_fa: ForAbuser[CompareQuery[E]]
+ do
+ return new SortAbuser[E](self)
+ end
+end
+
+####
+
+# Open and read a file trough a `for` abuse.
+# The abuse just ensures that the file is closed after the reading.
+#
+# for f in file_open(path) do
+# print path.read_line
+# end # f is automatically closed here
+fun file_open(path: String): ForAbuser[IFStream]
+do
+ return new ReadFileForAbuser(path)
+end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import for_abuse
+
+for f in file_open("test_for_abuse.nit") do
+ print f.read_line
+end
+
+var array = ["*", "****", "**", "*******"]
+for q in array.sort_fa do
+ q.res = q.b.length <=> q.b.length
+end
+