6.64. kink/iter/ITER

6.64.1. iter型

“iter”は“iterator”の略語である。iterは有限長、または無限長の値のストリームである。

iterはifunのラッパである。ifunについてはkink/iter/IFUNを見よ。

6.64.1.1. Iter.ifun

ifunメソッドは、Iterがラップしているifunを戻す。

:IFUN.require_from('kink/iter/')

:Num_iter <- 5.times

Num_iter.each{(:N) stdout.print_line(N.repr) }
# => 0 1 2 3 4

:nums <- Num_iter.ifun
IFUN.each($nums){(:N) stdout.print_line(N.repr) }
# => 0 1 2 3 4

6.64.1.2. Iter.each($consume)

eachはIterの各要素について$consumeを呼び出し、最後の$consumeの戻り値を戻す。

もしIterが要素を持たない場合、eachはnadaを戻す。

事前条件

$consumeはひとつの引数を取る関数でなければならない。

3.times.each{(:E)
  stdout.print_line(E.repr)
}
# Output:
#   0
#   1
#   2

6.64.1.3. Iter.map($transform)

mapは、N番目の要素がtransform(IterのN番目の要素)であるようなiterを戻す。

事前条件

$transformはひとつの引数を取らなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4)
:Doubles <- Ns.map{(:N) N * 2 }
Doubles.each{(:D)
  stdout.print_line(D.repr)
}
# Output:
#   2
#   4
#   6
#   8

6.64.1.4. Iter.concat_map($to_iter)

concat_mapは、to_iter(Iterの要素)の戻り値のiterを結合したiterを戻す。

事前条件

$to_iterは引数をひとつ取り、iterを戻さなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4)
:Mapped <- Ns.concat_map{(:N)
  N.times
}
Mapped.each{(:M) stdout.print_line(M.repr) }
# => 0 0 1 0 1 2 0 1 2 3

6.64.1.5. Iter.filter($include?)

filterはIterの要素のうち$include?を満たすものを、iterとして戻す。要素の順序は変わらない。

事前条件

$include?は述語でなければならない。

:ITER.require_from('kink/iter/')

:Orig <- ITER.of(1 2 3 4 5 6 7 8 9)
:Evens <- Orig.filter{(:N) N % 2 == 0 }
Evens.each{(:N)
  stdout.print_line(N.repr)
}
# Output:
#   2
#   4
#   6
#   8

6.64.1.6. Iter.count($counted?)

countは、Iterの要素のうち、$counted?を満たすものの数を戻す。

結果は整数のnum値である。

事前条件

$counted?は述語でなければならない。

:ITER.require_from('kink/iter/')

:Nums <- ITER.of(1 2 3 4 5 6 7 8 9)
:Count <- Nums.count{(:N) N % 2 == 0 }
stdout.print_line(Count.repr) # => 4

6.64.1.7. Iter.fold(Init $combine)

foldは、Initを種としてIterの要素を畳み込む。

Iterの要素がE1, E2, ,,, En_1, Enのとき、foldはcombine(combine(,,,combine(combine(Init E1) E2),,, En_1) En)を戻す。

Iterが空の場合、foldはInitを戻す。

事前条件

$combineはふたつの引数を取らなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.fold(100){(:X :Y) X + Y }.repr)  # => 115

6.64.1.8. Iter.reduce($combine ...[$empty_fallback])

reduceは、Iterの要素を相互に畳み込む。

Iterの要素がE1, E2, E3, ,,, En_1, Enのとき、reduceはcombine(combine(,,,combine(combine(E1 E2) E3),,, En_1) En)を戻す。

Iterの要素がEひとつのとき、reduceはEを戻す。

Iterが要素を持たず、$empty_fallbackが与えられているとき、reduceは$empty_fallbackを引数なしで末尾呼び出しする。

Iterが要素を持たず、$empty_fallbackが与えられていないとき、reduceは例外を投げる。

事前条件

$combineはふたつの引数を取らなければならない。

$empty_fallbackはサンクでなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.reduce{(:X :Y) X + Y }.repr)  # => 15

6.64.1.9. Iter.take_front(N)

take_frontは、Iterの最初のN個の要素をiterとして戻す。Iterの要素がN個より少ない場合、take_frontはIterの要素をすべて持つiterを戻す。

事前条件

Nは整数のnum値でなければならない。

:ITER.require_from('kink/iter/')

1.up.take_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 4 5

ITER.of(1 2 3).take_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3

6.64.1.10. Iter.drop_front(N)

drop_frontは、Iterの要素から最初のN個を除いて、iterとして戻す。Iterの要素がN個より少ない場合、drop_frontは空のiterを戻す。

事前条件

Nは整数のnum値でなければならない。

:ITER.require_from('kink/iter/')

10.times.drop_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 5 6 7 8 9

10.times.drop_front(20).each{(:N)
  stdout.print_line(N.repr)
}
# Output: nothing

6.64.1.11. Iter.take_while($include?)

take_whileは、すべての要素が$include?を満たすような、Iterの最長の先頭部分を、iterとして戻す。

事前条件

$include?は述語でなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1000 500 250 125 62 31 15 7 3 1 0)
:Front <- Ns.take_while{(:N) N % 2 == 0 }
Front.each{(:N) stdout.print_line(N.repr) }
# => 1000 500 250

6.64.1.12. Iter.drop_while($exclude?)

drop_whileは、すべての要素が$exclude?を満たすような、Iterの最長の先頭部分を取り除き、残りをiterとして戻す。

事前条件

$exclude?は述語でなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1000 500 250 125 62 31 15 7 3 1 0)
:Back <- Ns.drop_while{(:N) N % 2 == 0 }
Back.each{(:N) stdout.print_line(N.repr) }
# => 125 62 31 15 7 3 1 0

6.64.1.13. Iter.all?($match?)

all?は、Iterのすべての要素が$match?を満たすときにtrueを、そうでないときにfalseを戻す。

Iterが無限長のとき、all?は戻ることが保証されない。

事前条件

$match?は述語でなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.all?{(:N) N < 10 }.repr)      # => true
stdout.print_line(Ns.all?{(:N) N % 2 == 0 }.repr)  # => false

6.64.1.14. Iter.any?(...[$match?={ true }])

any?は、Iterのひとつ以上の要素が$match?を満たすときにtrueを、そうでないときにfalseを戻す。

Iterが無限長のとき、any?は戻ることが保証されない。

$match?のデフォルト値は{ true }である。したがって、$match?が渡されない場合、any?はIterが空でないかどうかを戻す。

事前条件

$match?は述語でなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.any?{(:N) N % 2 == 0 }.repr)  # => true
stdout.print_line(Ns.any?{(:N) N > 10 }.repr)      # => false

:ITER.require_from('kink/iter/')

stdout.print_line(ITER.of().any?.repr)    # => false
stdout.print_line(ITER.of(1).any?.repr)   # => true
stdout.print_line(ITER.of(1 2).any?.repr) # => true

6.64.1.15. Iter.concat

concatは、Iterの要素であるiterをつなげたiterを戻す。

事前条件

Iterは、iterを要素に持つiterでなければならない。

:ITER.require_from('kink/iter/')

:Nums <- ITER.of(1 2 3)
:Strs <- ITER.of('foo' 'bar')
:Bools <- ITER.of(true false)
ITER.of(Nums Strs Bools).concat.each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 "foo" "bar" true false

6.64.1.16. Iter.unconcat(Chunk_size)

unconcatは、Iterを、長さがChunk_sizeであるベクタに分割して、そのベクタのiterを戻す。

Iterの長さが有限値のChunk_size * N + R, ただしNとRは非負の整数, であるとき、Iterの最後のR個の要素は捨てられる。

事前条件

Chunk_sizeは正の整数でなければならない。

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5 6 7)
:Chunks <- Ns.unconcat(2)
Chunks.each{(:Chunk)
  stdout.print_line(Chunk.repr)
}
# Output:
#   [1 2]
#   [3 4]
#   [5 6]

6.64.1.17. Iter.cycle

cycleはIterの要素を無限に繰り返したiterを戻す。

Iterが空の場合、結果のiterも空である。

:ITER.require_from('kink/iter/')

3.times.cycle.take_front(10).each{(:N)
  stdout.print_line(N.repr)
}
# => 0 1 2 0 1 2 0 1 2 0

ITER.of().cycle.each{(:N)
  stdout.print_line(N.repr)
}
# Output: nothing

6.64.1.18. Front + Back

+演算子、つまりop_addメソッドは、ふたつのiterであるFrontとBackを、ひとつのiterにつなげる。

事前条件

FrontとBackはiter値でなければならない。

:Iter <- 1.up.take_front(3) + 11.up.take_front(3)
Iter.each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 11 12 13

6.64.2. ITER.new($ifun)

newは$ifunをラップするiterを戻す。

事前条件

$ifunはifunでなければならない。

:ITER.require_from('kink/iter/')

:make_vec_ifun <- {(:Vec)
  {(:proc :fin)
    if(Vec.any?
      { :Head = Vec.get(0)
        :tail = make_vec_ifun(Vec.drop_front(1))
        proc(Head $tail)
      }
      { fin }
    )
  }
}
:Iter <- ITER.new(make_vec_ifun(['foo' 'bar' 'baz']))
Iter.each{(:S)
  stdout.print_line(S)
}
# Output:
#   foo
#   bar
#   baz

6.64.3. ITER.is?(Val)

is?はValがiterであるかどうかを戻す。

6.64.4. ITER.of(...Elems)

ofはElemsの要素を含むiterを戻す。

:ITER.require_from('kink/iter/')

:Iter <- ITER.of('foo' 'bar' 'baz')
Iter.each{(:S)
  stdout.print_line(S)
}
# Output:
#   foo
#   bar
#   baz

6.64.5. ITER.zip(First_iter ...Other_iters)

zipは、N個のiterが渡された場合、最短のiterと同じ長さのiterを戻す。結果のiterの要素は、長さNのベクタであり、ベクタの要素は対応する位置の引数のiterの要素からななる。

たとえば、iter Xが要素X1, X2, X3, ,,, からなり、YがY1, Y2, Y3, ,,, からなり、ZがZ1, Z2, Z3, ,,,, からなるとき、zip(X Y Z)は[X1 Y1 Z1], [X2 Y2 Z2], [X3 Y3 Z3], ,,, を要素とするiterを戻す。

事前条件

Other_itersの要素はiterでなければならない。

:ITER.require_from('kink/iter/')

:Zipped <- ITER.zip(
  ITER.of(1 2 3 4 5)
  ITER.of('foo' 'bar' 'baz')
  ITER.of(true false true)
)
Zipped.each{(:Triple)
  stdout.print_line(Triple.repr)
}
# Output:
#   [1 "foo" true]
#   [2 "bar" false]
#   [3 "baz" true]

6.64.6. ITER.lazy($make_iter)

lazyは、$make_iterが戻したiterに要素の生成を委譲するようなiterを戻す。

サンク$make_iterは、結果のiterの内容が必要となった際に呼ばれる。

事前条件

$make_iterはiterを戻すサンクでなければならない。

:ITER.require_from('kink/iter/')

:count_down <- {(:N)
  if(N < 0
    { ITER.of() }
    { ITER.of(N) + ITER.lazy{ count_down(N - 1) } }
  )
}
count_down(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 5 4 3 2 1 0

6.64.7. ITER.from_generator($generator)

from_generatorは、$generatorの中で算出された要素を含むiterを戻す。

$generatorは、引数ひとつの関数$yieldを引数に取らなければならない。$generatorの呼び出しの中で$yieldが引数とともに呼ばれると、その引数が結果のiterの要素になる。$generatorの呼び出しが終わると、そこがiterの末尾になる。

$generatorは、結果のiterの内容が必要になったときに呼び出される。$generatorの呼び出しは、$yieldが呼ばれたときに中断される。呼び出しは、後続するiterの内容が必要になったときに再開される。

例: 有限長のiterを作る

:ITER.require_from('kink/iter/')

:Iter <- ITER.from_generator{(:yield)
  yield('foo')
  yield('bar')
  yield('baz')
}
Iter.each{(:Str)
  stdout.print_line(Str)
}
# Output:
#   foo
#   bar
#   baz

例: 無限長のiterを作る

:ITER.require_from('kink/iter/')

:Iter <- ITER.from_generator{(:yield)
  :loop <- {(:N)
    yield(N)
    loop(N + 1)
  }
  loop(1)
}
Iter.take_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# Output:
#   1
#   2
#   3
#   4
#   5

6.64.8. ITER.from_each(Eacher)

from_eachは、Eacher.eachで列挙される値を要素とするiterを戻す。

eachの呼び出しは、iterの要素が評価されるごとに中断、再開される。

事前条件

Eacherはeach($consume)メソッドをサポートしなければならない。eachはEacherの要素を列挙するために呼ばれる。

:ITER.require_from('kink/iter/')

:Take_five <- ITER.from_each([1 2 3 4 5])
Take_five.each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 4 5