For a certain code golf challenge I needed a way to abstract away the mess of dealing with stdin to make my code cleaner (and I can reuse this wherever, which is a big bonus). However, being accustomed to STDIN.each_line in ruby, I wanted an iterator instead of using a while loop in my SumApplication.run() method, so I spent an hour in the vala source figuring out how to write my own iterator that works with foreach(). Now I give this knowledge to you, so you don't have to spend the time yourself!
First, it's important to note that iterators in vala are designed for generic collections, so they make heavy use of the generic programming facilities provided by vala. This means that it's slightly more verbose to implement an iterator for something like my StdinReader class, or anything that isn't a generic collection, but it works.
So let's take a look at the source code for my whole sum app:
My SumApplication class is pretty typical for vala, it has a main() that creates a new application object and runs it, with all the logic being inside the run() method itself.
My StdinReader class, however, is slightly more complex. When specifying the Iterable and CollectionObject interfaces, I passed the string type to them since StdinReader only deals with strings (though that might change if I ever need to work with bytes or arbitrary datatypes, but for now I'm just dealing with text), but I used generic programming in the Iterator class since the Iterator interface requires it.
All of this is simple once you look at it, foreach() calls the objects iterator() method to get an Interator object with the methods next() and get(), which return whether there's another item and what the data of the current item is, respectively. This is a pretty simple interface, and if you need iterators it's simple to implement, but keep in mind you can only have one iterator per object.

Comments
Post new comment