Iterators
The overload Operators For, Next, and Step, allowing to construct User-Defined Types Iterators (instead of only intrinsic scalar types iterators) for a For...Next loop
Syntax (declaration)
{ Type | Class | Union } typename
' For...Next' statement with implicit step (1st version of operators)
End { Type | Class | Union }
declare Operator For ( )
declare Operator Next ( [ byref | byval ] cond as typename ) as Integer
declare Operator Step ( )
' For...Next' statement with explicit step (2nd version of operators)declare Operator Next ( [ byref | byval ] cond as typename ) as Integer
declare Operator Step ( )
Usage
For iterator [ As typename ] = start_value To end_value [ Step step_value ]
The first version of operators is used if no step_value is given in the For...Next statement.
If a step_value is given, the second version is used and a step object (initialized with step-value) is passed through the stp parameter:
[ ...statements... ]
NextThe first version of operators is used if no step_value is given in the For...Next statement.
If a step_value is given, the second version is used and a step object (initialized with step-value) is passed through the stp parameter:
- to Operator For because eventual additional initialization may use it,
- to Operator Next because testing for iterating end may depend on it,
- to Operator Step to increment the iterator object.
Both versions of the operators can coexist (thanks to member overloading) in the same user-defined type (to be able to both use and not use the explicit increment in For...Next statements of the user code).- to Operator Next because testing for iterating end may depend on it,
- to Operator Step to increment the iterator object.
Parameters
(including arguments)
typename
stp, step_value
stp, step_value
a typename object used as an incremental value
iterator
a typename object used as an iterator
cond, end_value
a typename object used as a loop-terminating value
start_value
a typename object used to copy construct or assign to the iterator initially
Description
Operator For, Operator Next and Operator Step can be overloaded in user-defined type definitions to allow objects of that type to be used as iterators and step values in For...Next loops (instead of the pre-defined for intrinsic scalar types).
As all non-static member procedures, the 3 operators have passed a hidden this parameter that allows to access by reference to the iterator object (initialized to the start_value argument value from the For...Next statement).
The cond parameter of the Operator Next allows to access the end_value argument value from the For...Next statement.
If a step_value is given (as argument) in the For...Next statement, the stp parameter allows to access this value in the 3 operators.
Note: If no step_value is given in the For...Next statement (implicit step), the user-defined type must have a default constructor (implicit or explicit) or a conversion constructor. It is a bug at the moment because if the user defines a default constructor, the compiler does not even use it when initializing the For...Next loop!
Operator For
As all non-static member procedures, the 3 operators have passed a hidden this parameter that allows to access by reference to the iterator object (initialized to the start_value argument value from the For...Next statement).
The cond parameter of the Operator Next allows to access the end_value argument value from the For...Next statement.
If a step_value is given (as argument) in the For...Next statement, the stp parameter allows to access this value in the 3 operators.
Note: If no step_value is given in the For...Next statement (implicit step), the user-defined type must have a default constructor (implicit or explicit) or a conversion constructor. It is a bug at the moment because if the user defines a default constructor, the compiler does not even use it when initializing the For...Next loop!
Operator For
Operator For is called once immediately after copy constructing or assigning to the iterator object (with the start_value), constructing the end object (with the end_value), and constructing the step object (with step_value if defined in the For...Next statement).
Operator For allows to perform any additional initialization needed in preparation for the loop.
Operator NextOperator For allows to perform any additional initialization needed in preparation for the loop.
Operator Next is called every time the iterator object needs to be checked against the end value. This happens immediately after the call to the Operator For, and then immediately after any calls to the Operator Step.
Operator Next should return zero (0) if the loop should be terminated, or non-zero if the loop should continue iterating.
The first time Operator Next is called, no statements in the For...Next body have been executed yet.
Operator Next also allows to perform some processing before the execution of all statements in the For...Next body.
Operator StepOperator Next should return zero (0) if the loop should be terminated, or non-zero if the loop should continue iterating.
The first time Operator Next is called, no statements in the For...Next body have been executed yet.
Operator Next also allows to perform some processing before the execution of all statements in the For...Next body.
Operator Step is called to increment the iterator object immediately after all statements in the For...Next body are executed.
Advanced usage
The above description seems to imply that the 3 arguments start_value, end_value, and step_value must be of the same type as the iterator (this is the more obvious use), but it is not quite true:
- The start_value, end_value, and step_value arguments can be of any type (of different types among themselves and also of different types from the one of the iterator).
- The only constraint is that the iterator could be constructed (in case of local iterator) or assigned (in case of global iterator) from the start_value argument (because the iterator is implicitly constructed or assigned under the hood).
- Similarly the other arguments end_value, and step_value must be able to be converted into objects of the same type as the iterator.
- The only constraint is that the iterator could be constructed (in case of local iterator) or assigned (in case of global iterator) from the start_value argument (because the iterator is implicitly constructed or assigned under the hood).
- Similarly the other arguments end_value, and step_value must be able to be converted into objects of the same type as the iterator.
Algorithm
For...Next loop algorithm around the 3 overload operators:
Example' FOR...NEXT loop ' V ' | ' constructing/assigning iterator object ' (This = start_value from For...Next statement) ' | ' constructing end object ' (cond = end_value from For...Next statement) ' | ' if step_value is defined >---------------------. ' else : ' v v ' : constructing step object ' : (stp = step_value from For...Next statement) ' : : ' :<----------------------------------' ' | ' calling Operator For ' | ' .----------------------->| ' | | ' | calling Operator Next ' | (if end-condition verified: =0 returned) >-------------. ' | (else: <>0 returned) | ' | v | ' | | | ' | executing For...Next body | ' | | | ' | calling Operator Step | ' | | | ' '------------------------' | ' | ' V
Type for iterating through screen resolutions, with implicit step-value:
Type for iterating through fractions, with explicit step-value used in the 3 operators:
(improved example compared to the one of Operator Step page)
See also
Type screenResolution
' user interface
Declare Constructor (ByVal colorBit As Long)
Declare Property colorDepth () As Long
Declare Property screenWidth () As Long
Declare Property screenHeigth () As Long
' overload iteration operators when Step is not defined in For...Next statement
Declare Operator For ()
Declare Operator Next (ByRef iterateCondition As screenResolution) As Integer
Declare Operator Step ()
' internal variables
Dim As Long colorBit, resolutionWH
End Type
Constructor screenResolution (ByVal colorBit As Long)
This.colorBit = colorBit
End Constructor
Property screenResolution.colorDepth () As Long
Return This.colorBit
End Property
Property screenResolution.screenWidth () As Long
Return HiWord(This.resolutionWH)
End Property
Property screenResolution.screenHeigth () As Long
Return LoWord(This.resolutionWH)
End Property
Operator screenResolution.For ()
This.resolutionWH = ScreenList(This.colorBit)
End Operator
Operator screenResolution.Next (ByRef iterateCondition As screenResolution) As Integer
While This.resolutionWH = 0
If This.colorBit < iterateCondition.colorBit Then
This.colorBit += 1
This.resolutionWH = ScreenList(This.colorBit)
Else
Exit While
End If
Wend
Return (This.resolutionWH <> iterateCondition.resolutionWH)
End Operator
Operator screenResolution.Step ()
This.resolutionWH = ScreenList()
End Operator
Print "Screen resolutions supported within [1 bpp , 64 bpp]:"
For iterator As screenResolution = screenResolution(1) To screenResolution(64)
Print " " & iterator.colorDepth & " bpp ",
Print ":" & iterator.screenWidth & "x" & iterator.screenHeigth
Next iterator
Print "End of supported screen resolutions"
Sleep
Output example:' user interface
Declare Constructor (ByVal colorBit As Long)
Declare Property colorDepth () As Long
Declare Property screenWidth () As Long
Declare Property screenHeigth () As Long
' overload iteration operators when Step is not defined in For...Next statement
Declare Operator For ()
Declare Operator Next (ByRef iterateCondition As screenResolution) As Integer
Declare Operator Step ()
' internal variables
Dim As Long colorBit, resolutionWH
End Type
Constructor screenResolution (ByVal colorBit As Long)
This.colorBit = colorBit
End Constructor
Property screenResolution.colorDepth () As Long
Return This.colorBit
End Property
Property screenResolution.screenWidth () As Long
Return HiWord(This.resolutionWH)
End Property
Property screenResolution.screenHeigth () As Long
Return LoWord(This.resolutionWH)
End Property
Operator screenResolution.For ()
This.resolutionWH = ScreenList(This.colorBit)
End Operator
Operator screenResolution.Next (ByRef iterateCondition As screenResolution) As Integer
While This.resolutionWH = 0
If This.colorBit < iterateCondition.colorBit Then
This.colorBit += 1
This.resolutionWH = ScreenList(This.colorBit)
Else
Exit While
End If
Wend
Return (This.resolutionWH <> iterateCondition.resolutionWH)
End Operator
Operator screenResolution.Step ()
This.resolutionWH = ScreenList()
End Operator
Print "Screen resolutions supported within [1 bpp , 64 bpp]:"
For iterator As screenResolution = screenResolution(1) To screenResolution(64)
Print " " & iterator.colorDepth & " bpp ",
Print ":" & iterator.screenWidth & "x" & iterator.screenHeigth
Next iterator
Print "End of supported screen resolutions"
Sleep
Screen resolutions supported within [1 bpp , 64 bpp]: 24 bpp :320x200 24 bpp :320x240 24 bpp :400x300 24 bpp :512x384 24 bpp :640x400 24 bpp :640x480 24 bpp :800x600 24 bpp :1024x768 24 bpp :1152x864 24 bpp :1280x600 24 bpp :1280x720 24 bpp :1280x768 24 bpp :1280x800 24 bpp :1280x960 24 bpp :1280x1024 24 bpp :1360x768 24 bpp :1366x768 24 bpp :1400x1050 24 bpp :1440x900 24 bpp :1600x900 24 bpp :1680x1050 24 bpp :1920x1080 32 bpp :320x200 32 bpp :320x240 32 bpp :400x300 32 bpp :512x384 32 bpp :640x400 32 bpp :640x480 32 bpp :800x600 32 bpp :1024x768 32 bpp :1152x864 32 bpp :1280x600 32 bpp :1280x720 32 bpp :1280x768 32 bpp :1280x800 32 bpp :1280x960 32 bpp :1280x1024 32 bpp :1360x768 32 bpp :1366x768 32 bpp :1400x1050 32 bpp :1440x900 32 bpp :1600x900 32 bpp :1680x1050 32 bpp :1920x1080 End of supported screen resolutions
(improved example compared to the one of Operator Step page)
Type fraction
' user interface
Declare Constructor (ByVal n As Integer, ByVal d As Integer)
Declare Operator Cast () As String
' overload iteration operators when Step is defined in For...Next statement
Declare Operator For (ByRef iterateStep As fraction)
Declare Operator Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
Declare Operator Step (ByRef step_var As fraction)
' internal variables and cast operator
As Integer num, den
Declare Operator Cast () As Double
End Type
Constructor fraction (ByVal n As Integer, ByVal d As Integer)
This.num = n
This.den = d
End Constructor
Operator fraction.Cast () As String
' search for the highest common factor (a) between numerator and denominator
Dim As Integer a = Abs(This.num), b = Abs(This.den)
If a <> 0 Then
While a <> b
If a > b Then
a -= b
Else
b -= a
End If
Wend
Else
a = 1
End If
' reduce the fraction
Return num \ a & "/" & den \ a
End Operator
Operator fraction.Cast () As Double
Return This.num / This.den
End Operator
Operator fraction.For (ByRef iterateStep As fraction)
' search for the least common multiple (a) between the two denominators
Dim As Integer a = Abs(This.den), b = Abs(iterateStep.den), c = a, d = b
While a <> b
If a > b Then
b += d
Else
a += c
End If
Wend
' align at the same denominator the 2 fractions
This.num *= a \ This.den
This.den = a
iterateStep.num *= a \ iterateStep.den
iterateStep.den = a
End Operator
Operator fraction.Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
If iterateStep.num < 0 Or iterateStep.den < 0 Then
Return This >= iterateCondition
Else
Return This <= iterateCondition
End If
End Operator
Operator fraction.Step (ByRef iterateStep As fraction)
This.num += iterateStep.num
End Operator
Print "iteration from 1/8 to 1/2 by step of 1/12:"
For iterator As fraction = fraction(1, 8) To fraction(1, 2) Step fraction(1, 12)
Print " " & iterator;
Next
Print
Print
Print "iteration from 7/10 to -8/5 by step of -8/15:"
For iterator As fraction = fraction(7, 10) To fraction(-8, 5) Step fraction(-8, 15)
Print " " & iterator;
Next
Print
Sleep
Output:' user interface
Declare Constructor (ByVal n As Integer, ByVal d As Integer)
Declare Operator Cast () As String
' overload iteration operators when Step is defined in For...Next statement
Declare Operator For (ByRef iterateStep As fraction)
Declare Operator Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
Declare Operator Step (ByRef step_var As fraction)
' internal variables and cast operator
As Integer num, den
Declare Operator Cast () As Double
End Type
Constructor fraction (ByVal n As Integer, ByVal d As Integer)
This.num = n
This.den = d
End Constructor
Operator fraction.Cast () As String
' search for the highest common factor (a) between numerator and denominator
Dim As Integer a = Abs(This.num), b = Abs(This.den)
If a <> 0 Then
While a <> b
If a > b Then
a -= b
Else
b -= a
End If
Wend
Else
a = 1
End If
' reduce the fraction
Return num \ a & "/" & den \ a
End Operator
Operator fraction.Cast () As Double
Return This.num / This.den
End Operator
Operator fraction.For (ByRef iterateStep As fraction)
' search for the least common multiple (a) between the two denominators
Dim As Integer a = Abs(This.den), b = Abs(iterateStep.den), c = a, d = b
While a <> b
If a > b Then
b += d
Else
a += c
End If
Wend
' align at the same denominator the 2 fractions
This.num *= a \ This.den
This.den = a
iterateStep.num *= a \ iterateStep.den
iterateStep.den = a
End Operator
Operator fraction.Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
If iterateStep.num < 0 Or iterateStep.den < 0 Then
Return This >= iterateCondition
Else
Return This <= iterateCondition
End If
End Operator
Operator fraction.Step (ByRef iterateStep As fraction)
This.num += iterateStep.num
End Operator
Print "iteration from 1/8 to 1/2 by step of 1/12:"
For iterator As fraction = fraction(1, 8) To fraction(1, 2) Step fraction(1, 12)
Print " " & iterator;
Next
Print "iteration from 7/10 to -8/5 by step of -8/15:"
For iterator As fraction = fraction(7, 10) To fraction(-8, 5) Step fraction(-8, 15)
Print " " & iterator;
Next
Sleep
iteration from 1/8 to 1/2 by step of 1/12: 1/8 5/24 7/24 3/8 11/24 iteration from 7/10 to -8/5 by step of -8/15: 7/10 1/6 -11/30 -9/10 -43/30
Back to Programmer's Guide