Breaking completely from my usual programming topics, which surround C# most of the time, today I will be looking at Some VB.NET, and, more generally, the topic of iterator methods. For quite some time, Visual Basic.NET has been something of the younger brother to C#; it usually got features long after C# did. Iterator methods are no exception.
An iterator method is a coroutine. The best way to describe it is to see it in action. Take the following C# Code as an example:
In this example, the code would output the values 0 through 24. The difference between this and say something like this:
Is one of both semantics as well as performance. In the first case, the iterator routine is only executed until the next yield, or the iterator routine returns. At which point, either the next element will be passed through the foreach body or the foreach loop will be finished. So, for example, the iterator version of SomeRange() will not iterate past 24 in this example, but the latter does, since it constructs the entire list, and that resulting list is then dealt with using the list enumerator.
One particularly useful purpose is for endless sequences; the second method is impossible for this, since you cannot simply fill a list with an infinite sequence. The iterator routine pattern allows you to define a sequence based on a larger code block by yielding specific values to the enumerating routine. Many other languages have support for the concept of iterator functions. Python, for example, has them, and they work very similarly:
In that example, itertest() is a “generator” or iterator function, just like the C# Example above. Because Python is a strongly-typed dynamic language, it has very few special things you need to do; basically, all you have to do is use yield instead of return. the C# Example has to use yield return, as well as having the function signature return a IEnumerable. C++ has a concept of iterator classes, which doesn’t make the syntax simple and “language-defined” but provides a well-defined set of abstract classes that can be relied on.
Visual Basic 6 is an interesting case. The language itself is quite limited. Of course it has absolutely no concept of iterators; it’s For…Each loop acts on an IEnumVariant interface, but you cannot even implement this interface yourself easily. Implementing IEnumVariant in VB6 is possible, but it requires a lot of manual hacking of virtual call tables to point to module-level functions, exacerbated by the fact that the IEnumVariant Interface has method names that are Visual Basic 6 reserved words.
Visual Basic .NET has been a bit better off than VB6 since inception; it doesn’t directly support iterator methods/coroutines yet (it will in VB10) But you can at least implement the IEnumerator interface. You do lose the ability to have the nice iterator syntax that C# and Python have, though.
It is, however, possible to sort of fake it with VB.NET, by creating your own implementation of an enumerator that accepts a delegate; that delegate is passed a single argument- the iterator object- which has two methods- Yield, and Break. Yield returns the next value in the sequence, and Break cancels the iteration. Note that the implementation I came up with does not work like the versions in either Python or C#; in both those cases, the compiler/interpreter turns the iterator function into a state machine. My implementation uses a threaded model- the MoveNext() routine waits until Yield or Break is called before returning. Here is the implementation I came up with. Bear in mind I don’t usually work with VB.NET…
Usage of this class is relatively simple, compared to having to write your own full blown Enumerable implementation. First, you need a method satisfying the delegate:
Note the use of ih.Yield() and ih.Break(), which “emulate” the appropriate statements from C# (Or Python, for that matter). Using it would look like this:
Sub Main() Dim iterate As Double For Each iterate In New Iterator(Of Double)(AddressOf testIterator) Console.WriteLine(iterate) Next Console.ReadKey() End Sub
It’s not as succint as the C# version but still a lot shorter.
Thankfully VB10 will remove this goofy problem- it adds support for iterator methods. Though it’s still a bit goofy, it does allow some things C# doesn’t such as anonymous iterator methods.
546 total views, no views today