Оператор Step (итерация)
 
Увеличивает итератор для цикла For...Next

Синтаксис

{ Type | Class | Union } typename
Declare Operator Step ()
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

Параметры

typename
имя Type, Class, или Union
stp, step_value
typename объект, используемый в качестве дополнительного значения
iterator
typename объект, используемый в качестве итератора
end_value
typename объект, используемый в качестве завершающего значения цикла
start_value
typename объект используется для копирования конструкции или назначения итератора изначально

Описание

Оператор For, Оператор Next и Оператор Step могут быть перегружены в определениях определяемого пользователем типа, чтобы позволить объектам этого типа использоваться в качестве итераторов и значений шага в циклах For...Next.

Оператор Step вызывается для увеличения итератора сразу же после всех выполняемых инструкций в теле цикла For...Next, если таковые выполняемые инструкции имеются.

Первая версия Оператора Step используется, если значение шага не установлено в заявлении For...Next. Если задано значение шага, то используется вторая версия и передается значение шага.

Пример

'' Пример типа
Type T
  '' значение устанавливается в конструкторе
  value As Double
  Declare Constructor( ByVal x As Double = 0 )

  Declare Operator For( ByRef stp As T )
  Declare Operator Step( ByRef stp As T )
  Declare Operator Next( ByRef cond As T, ByRef stp As T ) As Integer
End Type

Constructor T ( ByVal x As Double )
  Print "T iterator constructed with value " & x
  value = x
End Constructor

Operator T.for( ByRef stp As T )
End Operator

Operator T.step( ByRef stp As T )
  Print " incremented by " & stp.value & " in step."
  value += stp.value
End Operator

Operator T.next( ByRef cond As T, ByRef stp As T ) As Integer
  '' переход итератора от высокого значения до низкого значения (step >= 0)
  If( stp.value < 0 ) Then
    Return( value >= cond.value )
  Else
  '' итератор движется от низкого значения до высокого значения (step < 0)
    Return( value <= cond.value )
  End If
End Operator

'' Пример использования. Похоже, что мы работаем с числами, но итераторы
'' имеют перегруженные конструкторы. 10, 1, и -1 все из типа T.
For i As T = 10 To 1 Step -1
  Print i.value;
Next i

Более практичный пример, демонстрирующий файловую итерацию на основе класс итерации файлов от cha0s.
'' класс, который перебирает файлы
Type FileIter
    As String pathName, fileName
    Declare Constructor( ByRef pathName As String )

    Declare Operator For()
    Declare Operator Step()
    Declare Operator Next( ByRef endCond As FileIter) As Integer
End Type

Constructor FileIter( ByRef pathName As String )   
    this.pathName = pathName
End Constructor

Operator FileIter.for( )   
    fileName = Dir(pathName & "/*.*")   
End Operator

Operator FileIter.step( )   
    fileName = Dir("")
End Operator

Operator FileIter.next( ByRef endCond As FileIter ) As Integer
    Return(fileName <> endCond.pathName)   
    '' конструктор устанавливает имя пути и таким образом, мы проверяем
End Operator

'' пример кода
'' измените путь на любой нужный вам каталог
For i As FileIter = "./" To ""
    Print i.fileName
Next

Еще один пример работы со строками:
Type CharIterator
    '' используется для построения шага var
    Declare Constructor( ByVal r As ZString Ptr )
    
    '' неявные версии шага
    Declare Operator For ( )
    Declare Operator Step( )
    Declare Operator Next( ByRef end_cond As CharIterator ) As Integer
    
    '' явные версии шага
    Declare Operator For ( ByRef step_var As CharIterator )
    Declare Operator Step( ByRef step_var As CharIterator )
    Declare Operator Next( ByRef end_cond As CharIterator, ByRef step_var As CharIterator ) As Integer
    
    '' дает текущее "value"    
    Declare Operator Cast( ) As String
    
    Private:    
        '' данные
        value As String
        
        '' Этот элемент не нужен - мы могли бы использовать
        '' шаг переменной для каждой итерации - 
        '' но мы выбираем этот метод, так как у нас есть
        '' сравнения строк в противном случае. См. ниже.
        is_up As Integer
End Type

Constructor CharIterator( ByVal r As ZString Ptr )
    value = *r
End Constructor

Operator CharIterator.cast( ) As String
    Operator = value
End Operator

'' неявные версии шага
'' 
'' В этом примере мы интерпретируем неявный шаг
'' который всегда означает 'вверх'
Operator CharIterator.for( )
    Print "implicit step"
End Operator

Operator CharIterator.step( )
    value[0] += 1
End Operator 

Operator CharIterator.next( ByRef end_cond As CharIterator ) As Integer
    Return this.value <= end_cond.value
End Operator

'' явные версии шага
'' 
'' В этом примере мы вычислим направление
'' в FOR, но так как шаг var передается в
'' каждый оператор, у нас есть выбор, чтобы также рассчитать
'' это "на лету". Для строк, таких как эти, повторение сравнения
'' может наказываться, но если вы работаете с более простыми типами,
'' то вы можете предпочесть избежать накладных расходов на 
'' переменной 'is_up'.
Operator CharIterator.for( ByRef step_var As CharIterator )
    Print "explicit step"
    is_up = (step_var.value = "up")
End Operator

Operator CharIterator.step( ByRef step_var As CharIterator )
    If( is_up ) Then
        value[0] += 1
    Else
        value[0] -= 1
    End If
End Operator 

Operator CharIterator.next( ByRef end_cond As CharIterator, ByRef step_var As CharIterator ) As Integer
    If( this.is_up ) Then
        Return this.value <= end_cond.value
    Else
        Return this.value >= end_cond.value
    End If
End Operator

For i As CharIterator = "a" To "z"
    Print i; " ";
Next
Print "done"

For i As CharIterator = "a" To "z" Step "up"
    Print i; " ";
Next
Print "done"

For i As CharIterator = "z" To "a" Step "down"
    Print i; " ";
Next
Print "done"

For i As CharIterator = "z" To "a" Step "up"
    Print i; " ";
Next
Print "done"

Итерация с дробями:
Type fraction
    '' Используется для построения шага var
    Declare Constructor( ByVal n As Integer, ByVal d As Integer )

    '' неявные версии шага
    Declare Operator For ( )
    Declare Operator Step( )
    Declare Operator Next( ByRef end_cond As fraction ) As Integer

    '' явные версии шага
    Declare Operator For ( ByRef step_var As fraction )
    Declare Operator Step( ByRef step_var As fraction )
    Declare Operator Next( ByRef end_cond As fraction, ByRef step_var As fraction ) As Integer

    '' дает текущее "value"    
    Declare Operator Cast( ) As Double
    Declare Operator Cast( ) As String

    Private:
        As Integer num, den
End Type

Constructor fraction( ByVal n As Integer, ByVal d As Integer )
    this.num = n : this.den = d
End Constructor

Operator fraction.cast( ) As Double
    Operator = num / den
End Operator

Operator fraction.cast( ) As String
    Operator = num & "/" & den
End Operator

'' Некоторые функции фракции
Function gcd( ByVal n As Integer, ByVal m As Integer ) As Integer
    Dim As Integer t
        While m <> 0
            t = m
            m = n Mod m
            n = t
        Wend
    Return n
End Function

Function lcd( ByVal n As Integer, ByVal m As Integer ) As Integer
    Return (n * m) / gcd( n, m )
End Function

''
'' неявные версии шага
'' 
'' В этом примере мы интерпретируем неявный шаг
'' означающий 1
''
Operator fraction.for( )
    Print "implicit step"
End Operator

Operator fraction.step( )
    Var lowest = lcd( this.den, 1 )

    Var mult_factor = this.den / lowest
    Dim As fraction step_temp = fraction( 1, 1 )
    
    this.num *= mult_factor
    this.den *= mult_factor
    
    step_temp.num *= lowest
    step_temp.den *= lowest
    
    this.num += step_temp.num
End Operator 

Operator fraction.next( ByRef end_cond As fraction ) As Integer
    Return This <= end_cond
End Operator

''
'' явные версии шага
'' 
Operator fraction.for( ByRef step_var As fraction )
    Print "explicit step"
End Operator

Operator fraction.step( ByRef step_var As fraction )
    Var lowest = lcd( this.den, step_var.den )
    Var mult_factor = this.den / lowest
    Dim As fraction step_temp = step_var

    this.num *= mult_factor
    this.den *= mult_factor

    mult_factor = step_temp.den / lowest

    step_temp.num *= mult_factor
    step_temp.den *= mult_factor

    this.num += step_temp.num
End Operator 

Operator fraction.next( ByRef end_cond As fraction, ByRef step_var As fraction ) As Integer
    If(( step_var.num < 0 ) Or ( step_var.den < 0 ) ) Then
        Return This >= end_cond
    Else
        Return This <= end_cond
    End If
End Operator

For i As fraction = fraction(1,1) To fraction(4,1)
    Print i; " ";
Next
Print "done"

For i As fraction = fraction(1,4) To fraction(1,1) Step fraction(1,4)
    Print i; " ";
Next
Print "done"

For i As fraction = fraction(4,4) To fraction(1,4) Step fraction(-1,4)
    Print i; " ";
Next
Print "done"

For i As fraction = fraction(4,4) To fraction(1,4)
    Print i; " ";
Next
Print "done"

Различия диалектов

  • Доступно только в диалекте -lang fb.

См. также