Skip to content

迭代器 (Iterators)


重载 For、Next 和 Step 运算符,允许为 For...Next 循环构造用户自定义类型迭代器(而不仅仅是内置标量类型迭代器)

语法(声明)

{ Type | Class | Union } typename

带隐式步长的 For...Next 语句(第 1 版运算符)

declare Operator For ( )

declare Operator Next ( [ byref | byval ] cond as typename ) as Integer

declare Operator Step ( )

带显式步长的 For...Next 语句(第 2 版运算符)

declare Operator For ( [ byref | byval ] stp as typename )

declare Operator Next ( [ byref | byval ] cond as typename, [ byref | byval ] stp as typename ) as Integer

declare Operator Step ( [ byref | byval ] stp as typename )

End { Type | Class | Union }

用法

For iterator [ As typename ] = start_value To end_value [ Step step_value ]

[...statements...]

Next

如果 For...Next 语句中没有给出 step_value,则使用第 1 版运算符。

如果给出了 step_value,则使用第 2 版,并通过 stp 参数传递一个步长对象(用 step-value 初始化):

  • 传递给 Operator For,因为可能的额外初始化可能会用到它,

  • 传递给 Operator Next,因为迭代终止测试可能取决于它,

  • 传递给 Operator Step 以递增迭代器对象。

两个版本的运算符可以在同一用户自定义类型中共存(得益于成员重载),以便能够在用户代码的 For...Next 语句中同时使用和不使用显式增量。

参数

(包含参数)typename

TypeClassUnion 的名称

stpstep_value

用作增量值的 typename 对象

iterator

用作迭代器的 typename 对象

condend_value

用作循环终止值的 typename 对象

start_value

最初用于拷贝构造或赋值给迭代器的 typename 对象

描述

Operator ForOperator NextOperator Step 可以在用户自定义类型定义中重载,以允许该类型的对象在 For...Next 循环中用作迭代器和步长值(代替预定义的内置标量类型)。

与所有非静态成员过程一样,这 3 个运算符有一个隐藏的 this 参数,允许按引用访问迭代器对象(初始化为 For...Next 语句中的 start_value 参数值)。

Operator Nextcond 参数允许访问 For...Next 语句中的 end_value 参数值。

如果在 For...Next 语句中给出了 step_value(作为参数),stp 参数允许在 3 个运算符中访问该值。

注意:如果 For...Next 语句中没有给出 step_value(隐式步长),用户自定义类型必须有默认构造函数(隐式或显式)或转换构造函数。目前存在一个 bug,即如果用户定义了默认构造函数,编译器在初始化 For...Next 循环时甚至不使用它!

Operator For

Operator For 在对迭代器对象进行拷贝构造或赋值(使用 start_value)、构造 end 对象(使用 end_value)以及构造 step 对象(如果在 For...Next 语句中定义了 step_value)之后立即调用一次。

Operator For 允许执行循环准备所需的任何额外初始化。

Operator Next

Operator Next 在每次需要对照 end 值检查迭代器对象时调用。这发生在调用 Operator For 之后立即,然后在每次调用 Operator Step 之后立即。

如果循环应该终止,Operator Next 应该返回零(0),如果循环应该继续迭代,则返回非零值。

第一次调用 Operator Next 时,For...Next 体中的语句尚未执行。

Operator Next 还允许在执行 For...Next 体中的所有语句之前进行一些处理。

Operator Step

Operator Step 在执行 For...Next 体中的所有语句后立即调用,用于递增迭代器对象。

高级用法

上述描述似乎暗示 3 个参数 start_valueend_valuestep_value 必须与 iterator 的类型相同(这是更明显的用法),但这并不完全正确:

  • start_valueend_valuestep_value 参数可以是任何类型(彼此之间类型不同,也可以与 iterator 的类型不同)。

  • 唯一的约束是 iterator 可以从 start_value 参数构造(对于局部 iterator)或赋值(对于全局 iterator)(因为 iterator 在底层被隐式构造或赋值)。

  • 类似地,其他参数 end_valuestep_value 必须能够转换为与 iterator 类型相同的对象。

算法

围绕 3 个重载运算符的 For...Next 循环算法:

vb
'                       FOR...NEXT 循环
'                              V
'                              |
'            构造/赋值迭代器对象
'       (This = For...Next 语句中的 start_value)
'                              |
'                   构造结束对象
'       (cond = For...Next 语句中的 end_value)
'                              |
'                   若定义了 step_value >---------------------.
'                            否则                             :
'                              v                              v
'                              :                   构造步长对象
'                              :      (stp = For...Next 语句中的 step_value)
'                              :                             :
'                              :<---------------------------'
'                              |
'                    调用 Operator For
'                              |
'     .----------------------->|
'     |                        |
'     |              调用 Operator Next
'     |     (若结束条件成立:返回 =0)>------------------.
'     |               (否则:返回 <>0)                   |
'     |                        v                           |
'     |                        |                           |
'     |            执行 For...Next 循环体                  |
'     |                        |                           |
'     |              调用 Operator Step                    |
'     |                        |                           |
'     '------------------------'                           |
'                                                          |
'                                                          V

示例

用于遍历屏幕分辨率的类型,带隐式步长值:

start GeSHi

vb
Type screenResolution
    ' 用户接口
        Declare Constructor (ByVal colorBit As Long)
        Declare Property colorDepth () As Long
        Declare Property screenWidth () As Long
        Declare Property screenHeigth () As Long
    ' 重载迭代运算符(For...Next 语句中未定义 Step)
        Declare Operator For ()
        Declare Operator Next (ByRef iterateCondition As screenResolution) As Integer
        Declare Operator Step ()
    ' 内部变量
        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

end GeSHi

输出示例:

vb
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

用于遍历分数的类型,带在 3 个运算符中使用的显式步长值:

(相比 Operator Step 页面的示例有所改进)

start GeSHi

vb
Type fraction
    ' 用户接口
        Declare Constructor (ByVal n As Integer, ByVal d As Integer)
        Declare Operator Cast () As String
    ' 重载迭代运算符(For...Next 语句中定义了 Step)
        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)
    ' 内部变量 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
    ' 求分子和分母之间的最大公因数(a)
        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
    ' 化简分数
        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)
    ' 求两个分母之间的最小公倍数(a)
        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
    ' 将两个分数通分
        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

end GeSHi

输出:

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

参见

  • For...Next
  • Operator

返回 目录

基于 FreeBASIC 官方文档翻译 如有侵权请联系我们删除
FreeBASIC 是开源项目,与微软公司无隶属关系