6.27. kink/VEC

6.27.1. vec型

vecは、可変長で変更可能な値の列である。

vecの要素の添字は、0から始まって連続する整数である。

vecはplain_paramの部分型である。kink/param/PLAIN_PARAMを見よう。

6.27.1.1. Vec.get(Ind)

getは、添字Indに位置する要素を戻す。

事前条件

Indは、[0, Vec.size)の範囲内の整数のnumでなければならない。

:Vec <- ['foo' 'bar' 'baz']
stdout.print_line(Vec.get(0).repr)  # => "foo"
stdout.print_line(Vec.get(1).repr)  # => "bar"
stdout.print_line(Vec.get(2).repr)  # => "baz"

6.27.1.2. Vec.size

sizeは、Vecの要素の数を整数のnum値として戻す。

:Vec <- ['foo' 'bar' 'baz']
stdout.print_line(Vec.size.repr)  # => 3

6.27.1.3. Vec.front

frontは、Vecの最初の要素を戻す。

事前条件

Vecは空であってはならない。

stdout.print_line(['foo' 'bar' 'baz'].front.repr)  # => "foo"

6.27.1.4. Vec.back

backは、Vecの最後の要素を戻す。

事前条件

Vecは空であってはならない。

stdout.print_line(['foo' 'bar' 'baz'].back.repr)  # => "baz"

6.27.1.5. Vec.take_front(N)

take_frontは、Vecの最初のN個の要素を含む新しいvecを戻す。

事前条件

Nは、[0, Vec.size)の範囲内の整数のnumでなければならない。

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
stdout.print_line(Vec.take_front(2).repr) # => ["0" "1"]

6.27.1.6. Vec.take_back(N)

take_backは、Vecの最後のN個の要素を含む新しいvecを戻す。

事前条件

Nは、[0, Vec.size)の範囲内の整数のnumでなければならない。

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
stdout.print_line(Vec.take_back(2).repr) # => ["5" "6"]

6.27.1.7. Vec.drop_front(N)

drop_frontは、[N, Vec.size)の範囲のVecのスライスの要素を含む新しいvecを戻す。

事前条件

Nは、[0, Vec.size)の範囲内の整数のnumでなければならない。

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
stdout.print_line(Vec.drop_front(2).repr) # => ["2" "3" "4" "5" "6"]

6.27.1.8. Vec.drop_back(N)

drop_backは、[0, Vec.size - N)の範囲のVecのスライスの要素を含む新しいvecを戻す。

事前条件

Nは、[0, Vec.size)の範囲内の整数のnumでなければならない。

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
stdout.print_line(Vec.drop_back(2).repr) # => ["0" "1" "2" "3" "4"]

6.27.1.9. Vec.slice(From To)

sliceは、[From, To)の範囲のVecのスライスの要素を含む新しいvecを戻す。

事前条件

FromとToは整数のnum値でなければならない。

0 <= From <= To <= Vec.size

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
stdout.print_line(Vec.slice(1 4).repr) # => ["1" "2" "3"]

6.27.1.10. Vec.set(Ind Val)

setは、添字Indの位置にValを書き込む。

Vecのサイズは変わらない。

事前条件

Indは、[0, Vec.size)の範囲内の整数のnumでなければならない。

:Vec <- ['foo' 'bar' 'baz']
Vec.set(1 'X')
stdout.print_line(Vec.repr) # => ["foo" "X" "baz']

6.27.1.11. Vec.push_front(Val)

push_frontは、ValをVecの最初の要素として挿入する。

Vecのサイズは1だけ伸びる。既存の要素は後方に1だけコピーされる。

:Vec <- ['0' '1' '2' '3']
Vec.push_front('X')
stdout.print_line(Vec.repr) # => ["X" "0" "1" "2" "3"]

6.27.1.12. Vec.push_back(Val)

push_backはValをVecの最後の要素として挿入する。

Vecのサイズは1だけ伸びる。

:Vec <- ['0' '1' '2' '3']
Vec.push_back('X')
stdout.print_line(Vec.repr) # => ["0" "1" "2" "3" "X"]

6.27.1.13. Vec.push_at(Pos Val)

push_atはValを添字Posの位置に挿入する。

Vecのサイズは1だけ伸びる。Posの位置以降の既存の要素は、後方に1だけコピーされる。

事前条件

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

0 <= Pos <= Vec.size

:Vec <- ['foo' 'bar' 'baz']
Vec.push_at(2 'X')
stdout.print_line(Vec.repr) # => ["foo" "bar" "X" "baz"]

6.27.1.14. Vec.append_front(Eacher)

append_frontは、Eacherのすべての要素をVecの先頭に挿入する。

Eacher.eachが、それぞれの$consumeの呼び出しでE(0), E(1) ,,, E(n-1)を渡すとき、またVecの現在の要素がV(0), V(1) ,,, V(m-1)であるとき、append_frontの呼び出し後に、Vecの要素はE(0), E(1) ,,, E(n-1), V(0), V(1) ,,, V(m-1)になる。

事前条件

Eacherは each($consume) メソッドを持っていなければならない。eachは$consumeをEacherのそれぞれの要素について呼び出すものでなければならない。

:Vec <- ['foo' 'bar' 'baz' 'qux' 'grault']
Vec.append_front(['X' 'Y' 'Z'])
stdout.print_line(Vec.repr)
# => ["X" "Y" "Z" "foo" "bar" "baz" "qux" "grault"]

6.27.1.15. Vec.append_back(Eacher)

append_backは、Eacherのすべての要素をVecの末尾に挿入する。

Eacher.eachが、それぞれの$consumeの呼び出しでE(0), E(1) ,,, E(n-1)を渡すとき、またVecの現在の要素がV(0), V(1) ,,, V(m-1)であるとき、append_backの呼び出し後に、Vecの要素はV(0), V(1) ,,, V(m-1), E(0), E(1) ,,, E(n-1)になる。

事前条件

Eacherは each($consume) メソッドを持っていなければならない。eachは$consumeをEacherのそれぞれの要素について呼び出すものでなければならない。

:Vec <- ['foo' 'bar' 'baz' 'qux' 'grault']
Vec.append_back(['X' 'Y' 'Z'])
stdout.print_line(Vec.repr)
# => ["foo" "bar" "baz" "qux" "grault" "X" "Y" "Z"]

6.27.1.16. Vec.append_at(Pos Eacher)

append_atは、Eacherのすべての要素を、Vecの添字Posの位置に挿入する。

Eacher.eachが、それぞれの$consumeの呼び出しでE(0), E(1) ,,, E(n-1)を渡すとき、またVecの現在の要素がV(0), V(1) ,,, V(m-1)であるときappend_atの呼び出し後に、Vecの要素はV(0), V(1) ,,, V(Pos-1), E(0), E(1) ,,, E(n-1), V(Pos) ,,, V(m-1)になる。

事前条件

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

0 <= Pos <= Vec.size

Eacherは each($consume) メソッドを持っていなければならない。eachは$consumeをEacherのそれぞれの要素について呼び出すものでなければならない。

:Vec <- ['foo' 'bar' 'baz' 'qux' 'grault']
Vec.append_at(2 ['X' 'Y' 'Z'])
stdout.print_line(Vec.repr)
# => ["foo" "bar" "X" "Y" "Z" "baz" "qux" "grault"]

6.27.1.17. Vec.pop_front

pop_frontは、Vecの最初の要素を削除して、その要素を戻す。

削除された要素の後ろの要素は、先頭の方へ1ずつコピーされる。Vecのサイズは1だけ切り詰められる。

事前条件

Vecは空であってはならない。

:Vec <- ['foo' 'bar' 'baz' 'qux' 'grault']
:Result <- Vec.pop_front
stdout.print_line(Result.repr)  # => "foo"
stdout.print_line(Vec.repr)     # => ["bar" "baz" "qux" "grault"]

6.27.1.18. Vec.pop_back

pop_backは、Vecの最後の要素を削除して、その要素を戻す。

Vecのサイズは1だけ切り詰められる。

事前条件

Vecは空であってはならない。

:Vec <- ['foo' 'bar' 'baz' 'qux' 'grault']
:Result <- Vec.pop_back
stdout.print_line(Result.repr)  # => "grault"
stdout.print_line(Vec.repr)     # => ["foo" "bar" "baz" "qux"]

6.27.1.19. Vec.pop_at(Ind)

pop_atは、添字Indの位置の要素を削除して、その要素を戻す。

削除された要素の後ろの要素は、先頭の方へ1ずつコピーされる。Vecのサイズは1だけ切り詰められる。

事前条件

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

0 <= Ind < Vec.size

:Vec <- ['foo' 'bar' 'baz' 'qux' 'grault']
:Result <- Vec.pop_at(1)
stdout.print_line(Result)   # => "bar"
stdout.print_line(Vec.repr) # => ["foo" "baz" "qux" "grault"]

6.27.1.20. Vec.clear(...[From=0 To=Vec.size])

clearは、Vecの要素から[From, To)の範囲のスライスを削除する。

削除されたスライスの後の要素は、(To - From)ずつ先頭の方にコピーされる。VecのサイズはVec.size - (To - From)に切り詰められる。

事前条件

FromとToは整数のnum値でなければならない。

0 <= From <= To <= Vec.size

例: 引数なし

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
Vec.clear
stdout.print_line(Vec.repr)
# => []

例: Fromを指定

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
Vec.clear(3)
stdout.print_line(Vec.repr)
# => ["0" "1" "2"]

例: FromとToを指定

:Vec <- ['0' '1' '2' '3' '4' '5' '6']
Vec.clear(3 5)
stdout.print_line(Vec.repr)
# => ["0" "1" "2" "5" "6"]

6.27.1.21. Vec.dup

dupは、Vecと同じ要素の列を持つ新しいvecを戻す。

:Orig <- ['foo' 'bar' 'baz']
:Dup <- Orig.dup
Orig.set(0 'X')
Dup.set(1 'Y')
stdout.print_line(Orig.repr)  # => ["X" 'bar" "baz"]
stdout.print_line(Dup.repr)   # => ["foo" 'Y" "baz"]

6.27.1.22. Vec.reverse

reverseは、Vecと同じ要素を逆順で持つ新しいvecを戻す。

:Vec <- ['0' '1' '2' '3']
stdout.print_line(Vec.reverse.repr)  # => ["3" "2" "1" "0"]

6.27.1.23. Vec.concat

concatは、Vecの中のvecをつなぎ合わせる。

concatは、Vecの要素がすべてvecであると想定する。concatは、これらのvecの要素をすべて持つ新しいvecを戻す。要素は、これらのvecの順番で、またvecの中の要素の順番で現れる。

事前条件

Vecの要素はすべてvecでなければならない。

:Vecs <- [['0' '1'] ['2' '3'] ['4']]
stdout.print_line(Vecs.concat.repr) # => ["0" "1" "2" "3" "4"]

6.27.1.24. Vec.unconcat(N)

unconcatは、Vecの要素をN個ずつに分割して、それらN個の要素を含むvecのを要素とするvecをもどす。

Vecの要素がE(0), E(1) ,,, E(N-1), E(N), E(N+1) ,,, E(N+(N-1)) ,,, E(m*N), E(m*N+1) ,,, E(m*N+(N-1))のとき、結果のvecは、[E(0) E(1) ,,, E(N-1)], [E(N) E(N+1) ,,, E(N+(N-1))] ,,, [E(m*N) E(m*N+1) ,,, E(m*N+(N-1))]を含む。

事前条件

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

Vec.size % N == 0

:Vec <- ['0' '1' '2' '3' '4' '5']
stdout.print_line(Vec.unconcat(2).repr) # => [["0" "1"] ["2" "3"] ["4" "5"]]

6.27.1.25. Vec.just(...[$if_empty])

justはVecが1要素であるとき、その要素を戻す。

Vecが空で、$if_emptyが渡されているとき、justは$if_emptyを末尾呼び出しする。

それ以外の場合、justは例外を投げる。

事前条件

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

stdout.print_line([42].just.repr)  # => 42
stdout.print_line([].just{ 'empty' }.repr)  # => "empty"

[].just
# Output:
#   -- main exception
#   ,,,
#   {(stdin) L4 C4 just} [].-->just
#   Vec.just(...[$if_empty]): Vec must be a 1-elem vec, but the number of elems was 0

6.27.1.26. Vec.with_elems(...[$with0 $with1 $with2 ,,,])

with_elemsは、Vecの要素を引数として関数を末尾呼び出しする。

with_elemsは任意個数の関数を取る。これらを順番に、$with0, $with1, $with2, ,,, と呼ぶ。VecのサイズがNのとき、with_elemsは、Vecの要素を引数として$withNを末尾呼び出しする。

事前条件

Vecのサイズは、引数の数よりも小さくなければならない。

$withK (k = 0, 1, 2, ,,,) はK個の引数を取らなければならない。

:LOCALE.require_from('kink/')

:print_num <- {(:Num :Lang_tag.opt)
  :Locale = Lang_tag.with_elems(
    { LOCALE.root }
    {(:Lt) LOCALE.for(Lt) }
  )
  stdout.print_line(
    Num.show{(:C)
      C.locale(Locale)
      C.group_len(3)
    }
  )
}

print_num(1234)       # => 1,234
print_num(1234 'fr')  # => 1 234

6.27.1.27. Vec.each($consume)

eachは、先頭から末尾に向けて、それぞれの要素について$consumeを呼び出す。

Vecが空でない場合、eachは最後の要素について$consumeを末尾呼び出しする。

事前条件

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

:Vec <- ['foo' 'bar' 'baz']
Vec.each{(:E)
  stdout.print_line(E.repr)
}
# Output:
#   "foo"
#   "bar"
#   "baz"

6.27.1.28. Vec.map($transform)

mapは、Vecの要素を$transformで変換した要素を含むvecを戻す。

Vecの要素がE(0), E(1) ,,, E(n-1)のとき、結果のvecの要素はtransform(E(0)) transform(E(1)) ,,, transform(E(n-1))になる。

事前条件

$transformは、ひとつの値を取る関数でなければならない。

:Vec <- [0 1 2 3 4]
:Mapped <- Vec.map{(:N) N * 10 }
stdout.print_line(Mapped.repr)  # => [0 10 20 30 40]

6.27.1.29. Vec.concat_map($to_vec)

concat_mapは、to_vec(Vecの要素)の結果であるvecを結合したvecを戻す。

事前条件

$to_vecは、ひとつの値を取ってvecを戻す関数でなければならない。

# extracts codepoints from the strs
:to_codepoints <- {(:Strs)
  Strs.concat_map{(:S)
    S.codepoints
  }
}
:Codepoints <- to_codepoints(['foo' 'bar' 'baz'])
stdout.print_line(Codepoints.repr)
# => [102 111 111 98 97 114 98 97 122]

6.27.1.30. Vec.filter($include?)

filterは、述語$include?を満たすすべての要素を含むvecを戻す。

事前条件

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

:Nums <- [1 2 3 5 8 13 21 34 55 89]
:Evens <- Nums.filter{(:N)
  N % 2 == 0
}
stdout.print_line(Evens.repr) # => [2 8 34]

6.27.1.31. Vec.count($counted?)

countは、述語$counted?を満たす要素の数を整数のnumとして戻す。

事前条件

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

:Nums <- [1 2 3 5 8 13 21 34 55 89]
:Even_count <- Nums.count{(:N)
  N % 2 == 0
}
stdout.print_line(Even_count.repr) # => 3

6.27.1.32. Vec.fold(Init $combine)

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

Vecの要素がE(0) E(1) ,,, E(n-1)のとき、結果はcombine(combine(,,, combine(combine(Init E(0)) E(1)) ,,,) E(n-1))になる。

事前条件

$combineは、ふたつの値を取る関数でなければならない。

:to_quote_line <- {(:Words)
  Words.fold('%'){(:Accum :Word)
    Accum + ' ' + Word
  }
}
:Quote <- to_quote_line(['foo' 'bar' 'baz'])
stdout.print_line(Quote.repr) # => "% foo bar baz"

6.27.1.33. Vec.reduce($combine ...[$empty_fallback])

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

Vecが1個以上の要素を持っているとき、reduceはVec.drop_front(1).fold(Vec.front $combine)を末尾呼び出しする。

Vecが空で、$empty_fallbackが与えられているとき、reduceは$empty_fallbackを引数なしで末尾呼び出しする。

Vecが空で、$empty_fallbackが与えられなかったとき、reduceは例外を投げる。

事前条件

$combineは、ふたつの値を取る関数でなければならない。

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

例: フォールバックなし

:COMPARE.require_from('kink/')

stdout.print_line([31 41 59 26 53].reduce(COMPARE$max).repr) # => 59

例: フォールバックあり

:separate_by_commas <- {(:Args)
  Args.reduce(
    {(:Accum :Arg) Accum + ', ' + Arg }
    { '' }
  )
}

stdout.print_line(separate_by_commas(['foo' 'bar' 'baz']).repr)
# => "foo, bar, baz"

stdout.print_line(separate_by_commas([]).repr)
# => ""

6.27.1.34. Vec.take_while($include?)

take_whileは、要素が述語$include?を満たすような最長の先頭部分のvecを戻す。

事前条件

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

:Nums <- [1 (-2) 3 (-4) 5 (-6) 7 (-8)]
:Prefix <- Nums.take_while{(:N)
  N < 5
}
stdout.print_line(Prefix.repr)
# => [1 (-2) 3 (-4)]

6.27.1.35. Vec.drop_while($exclude?)

drop_whileは、要素が述語$exclude?を満たすような最長の先頭部分の後の要素のvecを戻す。

事前条件

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

:Nums <- [1 (-2) 3 (-4) 5 (-6) 7 (-8)]
:Suffix <- Nums.drop_while{(:N)
  N < 5
}
stdout.print_line(Suffix.repr)
# => [5 (-6) 7 (-8)]

6.27.1.36. Vec.all?($match?)

all?は、Vecのすべての要素が述語$match?を満たすかどうかを戻す。

事前条件

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

:all_even? <- {(:Nums)
  Nums.all?{(:N)
    N % 2 == 0
  }
}
stdout.print_line(all_even?([0 2 4]).repr)  # => true
stdout.print_line(all_even?([6 7 9]).repr)  # => false
stdout.print_line(all_even?([1 3 5]).repr)  # => false

6.27.1.37. Vec.any?(...[$match?={ true }])

any?は、Vecの要素のひとつ以上が述語$match?を満たすかどうかを戻す。

$match?はオプショナル引数であり、そのデフォルト値は{ true }である。したがって、$match?が渡されなければ、any?はVecが空でないかどうかを戻す。

事前条件

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

:any_even? <- {(:Nums)
  Nums.any?{(:N)
    N % 2 == 0
  }
}
stdout.print_line(any_even?([0 2 4]).repr)  # => true
stdout.print_line(any_even?([6 7 9]).repr)  # => true
stdout.print_line(any_even?([1 3 5]).repr)  # => false

stdout.print_line([].any?.repr) # => false
stdout.print_line(['foo'].any?.repr) # => true
stdout.print_line(['foo' 'bar'].any?.repr) # => true

6.27.1.38. Vec.have?(Target)

have?は、 == 演算子、つまりop_eqメソッドにおいて、Targetと等しい要素をVecが持っているかどうかを戻す。

Vec.have?(Target)を呼ぶことは、Vec.any?{(:E) Target == E }を呼ぶことと等しい。

stdout.print_line([1 3 5].have?(3).repr)  # => true
stdout.print_line([2 4 6].have?(3).repr)  # => false

6.27.1.39. Vec.have_all?(Vals)

have_all?は、Valsのすべての要素をVecが持っているかどうかを戻す。

Vec.have_all?(Vals)を呼ぶことは、Vals.all?{(:T) Vec.have?(T) }を呼ぶことと等しい。

事前条件

Valsは、all?($match?)メソッドを持っていなければならない。

== 演算子、つまりop_eqメソッドで、Vecの要素とValsの要素が比較できなければならない。

:FLAT_SET.require_from('kink/container/')

:Vec <- [2 4 6 8]
stdout.print_line(Vec.have_all?(FLAT_SET.of(2 4)).repr) # => true
stdout.print_line(Vec.have_all?(FLAT_SET.of(6 7)).repr) # => false

6.27.1.40. Vec.have_any?(Vals)

have_any?は、Valsのひとつ以上の要素をVecが持っているかどうかを戻す。

Vec.have_any?(Vals)を呼ぶことは、Vals.any?{(:T) Vec.have?(T) }を呼ぶことと等しい。

事前条件

Valsは、any?($match?)メソッドを持っていなければならない。

== 演算子、つまりop_eqメソッドで、Vecの要素とValsの要素が比較できなければならない。

:FLAT_SET.require_from('kink/container/')

:Vec <- [2 4 6 8]
stdout.print_line(Vec.have_any?(FLAT_SET.of(2 4)).repr)   # => true
stdout.print_line(Vec.have_any?(FLAT_SET.of(6 7)).repr)   # => true
stdout.print_line(Vec.have_any?(FLAT_SET.of(10 20)).repr) # => false

6.27.1.41. Vec.sort(...[$in_order?={(:X :Y) X <= Y }])

sortは、要素をVecからコピーして、$in_order?によって昇順に整列したvecを戻す。

比較

要素の比較は$in_order?によって行う。

$in_order?はVecの要素についての全順序関係でなければならない。Vecの要素中のすべてのX, Y, Zについて、$in_order?は次を満たさなければならない。

• 反射律: in_order?(X X)

• 推移律: if in_order?(X Y) && in_order?(Y Z) then in_order?(X Z)

• 反対称律: if in_order?(X Y) && in_order?(Y X) then X is equivalent to Y

• 狭義の連結律: in_order?(X Y) || in_order?(Y X)

安定ソート

sortは安定ソートを行う。Vecの要素E1, E2についてin_order?(E1 E2) && in_order(E2 E1)のとき、E1とE2はVecの中と同じ順番で結果のvecに現れる。

事前条件

$in_order?は、ふたつの値を取ってboolを戻す関数でなければならない。

:Vec <- ['foo' 'bar' 'baz' 'FOO' 'BAR' 'BAZ']

stdout.print_line(Vec.sort.repr)
# => ["BAR" "BAZ" "FOO" "bar" "baz" "foo"]

stdout.print_line(Vec.sort{(:X :Y) X.ascii_downcase <= Y.ascii_downcase }.repr)
# => ["bar" "BAR" "baz" "BAZ" "foo" "FOO"]

6.27.1.42. Vec.iter(...[From=0 To=Vec.size])

iterメソッドは、[From, To)の範囲のスライスの要素を含むiterを戻す。

事前条件

FromとToは整数のnum値でなければならない。

0 <= From <= To <= Vec.size

['0' '1' '2' '3' '4'].iter.each{(:S)
  stdout.print_line(S.repr)
}
# Output:
#   "0"
#   "1"
#   "2"
#   "3"
#   "4"

['0' '1' '2' '3' '4'].iter(2).each{(:S)
  stdout.print_line(S.repr)
}
# Output:
#   "2"
#   "3"
#   "4"

['0' '1' '2' '3' '4'].iter(2 4).each{(:S)
  stdout.print_line(S.repr)
}
# Output:
#   "2"
#   "3"

6.27.1.43. Vec1 + Vec2

+ 演算子、つまりop_addメソッドは、Vec1のすべての要素を先頭に、Vec2のすべての要素を末尾に置いたvecを戻す。

事前条件

Vec2はvec値でなければならない。

stdout.print_line((['0' '1'] + ['2' '3']).repr) # => ["0" "1" "2" "3"]

6.27.1.44. Vec * N

* 演算子、つまりop_mulメソッドは、Vecの要素をN回繰り返したvecを戻す。

事前条件

Nは、非負の整数のnumでなければならない。

stdout.print_line(([1 2] * 3).repr) # => [1 2 1 2 1 2]

6.27.1.45. Vec1 == Vec2

== 演算子、つまりop_eqメソッドは、Vec1とVec2が等しいか、つまり、ふたつのvecが同じ順番で同値の要素を持っているかどうかを戻す。

ふたつのvecは次の場合に等しい:

1) Vec1.size == Vec2.size

2) [0, Vec1.size]の範囲のすべてのiについて、Vec1.get(i) == Vec2.get(i)

上記の条件は順番に評価される。また、小さい i から大きい i にかけて評価される。どこかで比較がfalseを戻したら、以降の比較は評価されず、ふたつのvecは等しくないと決まる。

事前条件

Vec1とVec2はvec値でなければならない。

:CONTROL.require_from('kink/')

:test_equality <- {(:Vec1 :Vec2)
  CONTROL.try(
    { Vec1 == Vec2 }
    {(:Result) stdout.print_line(Result.repr) }
    {(:Exc)
      stdout.print_line('op_eq: exception: {}'.format(Exc.message))
    }
  )
}

# equal
test_equality(['foo' 42] ['foo' 42])
# Output: true

# not equal because sizes differ
test_equality(['foo' 42] ['foo' 42 'bar'])
# Output: false

# not equal because the first elemenets differ
test_equality(['foo' 42] ['bar' 42])
# Output: false

# not equal because the first elemenets differ;
# the second elements are not tested
test_equality(['foo' 42] ['bar' '***'])
# Output: false

test_equality(['foo' 42] ['foo' '***'])
# Output:
#   op_eq: exception: Num1.op_eq(Num2): the arg must be an int num, but got "***"

6.27.1.46. Vec1 <= Vec2

<= 演算子、つまりop_leメソッドは、要素同士の <= 演算子で定義される順序で、Vec1がVec2以下であるかどうかを戻す。

Vec1は、次の場合にVec2以下である。

1) [0, k) 内のすべてのiについて、Vec1.get(i) <= Vec2.get(i) && Vec2.get(i) <= Vec1.get(i)かつ、! (Vec2.get(k) <= Vec1.get(k))となる非負の整数k (k < min(Vec1.size Vec2.size))が存在する場合、または

2) Vec1.size <= Vec2.sizeであり、[0, Vec1.size)内のすべてのiについて、Vec1.get(i) <= Vec2.get(i) && Vec2.get(i) <= Vec1.get(i)である場合。

比較は小さい添字から大きい添字に向けて行われる。結果が途中で判明した場合、後続する比較は行われない。

事前条件

Vec2はvec値でなければならない。

:compare <- {(:Vec1 :Vec2)
  [:Lt? :Le? :Gt? :Ge?] = [
    Vec1 < Vec2
    Vec1 <= Vec2
    Vec1 > Vec2
    Vec1 >= Vec2
  ]
  stdout.print_line(
    'Lt?={} Le?={} Gt?={} Ge?={}'.format(Lt?.repr Le?.repr Gt?.repr Ge?.repr))
}

compare(['A' 42] ['A' 42])
# => Lt?=false Le?=true Gt?=false Ge?=true

compare(['A' 42] ['A' 42 'foo'])
# => Lt?=true Le?=true Gt?=false Ge?=false

compare(['A' 42] ['A'])
# => Lt?=false Le?=false Gt?=true Ge?=true

compare(['A' 42] ['B' 42])
# => Lt?=true Le?=true Gt?=false Ge?=false

compare(['A' 42] ['A' 84])
# => Lt?=true Le?=true Gt?=false Ge?=false

6.27.1.47. Lhs <- Rhs

<- 演算子、つまりop_storeメソッドは、左辺のvecであるLhsと、右辺のvecであるRhsの間で多重代入を行う。

ここで、Lhsの要素はパラメータと、Rhsの要素は引数と呼ぶ。

パラメータと引数

パラメータには三つの種類がある。

• plain_param: ex. varref, vec. 1個の引数が受け取れる。

• opt_param: ex. Varref.opt. 0個か1個の引数が受け取れる。

• rest_param: ex. Varref.rest. 任意の数の引数が受け取れる。

plain_paramとopt_paramは、Lhsの中で任意の回数現れられる。opt_paramが、plain_paramの前に現れてはならない。

Lhsは、末尾に0個か1個のrest_paramが持てる。

NPをplain_paramの数、NOをopt_paramの数とする。ここで、P(0), P(1) ,,, P(NP-1), O(0), O(1) ,,, O(NO-1)がパラメータである。(0 <= i < NP)のそれぞれのiについてP(i)はplain_param、(0 <= j < NO)のそれぞれのjについてO(j)はopt_paramである。

加えて、NAを引数の数、(0 <= k < NA)のそれぞれのkについて、A(k)を引数とする。

Lhsがrest_paramを持つかどうかによって、op_storeのふるまいは変わる。

Lhsがrest_paramを持たない場合

この場合、引数の数NAは、NP <= NA <= NP+NOのときに正しい。

引数の数が正しくないとき、op_storeは例外を投げる。

引数の数が正しいとき、op_storeは、それぞれのパラメータについて次のようにメソッドを呼ぶ。

• P(k).op_store(A(k)) for each k (0 <= k < NP)

• O(k - NP).pass_arg(A(k)) for each k (NP <= k < NA)

• O(k - NP).pass_nothing for each k (NA <= k < NP+NO)

Lhsがrest_param、Rを持つ場合

この場合、引数の数NAは、NP <= NAのときに正しい。

引数の数が正しくないとき、op_storeは例外を投げる。

引数の数が正しいとき、op_storeは、それぞれのパラメータについて次のようにメソッドを呼ぶ。

• P(k).op_store(A(k)) for each k (0 <= k < NP)

• O(k - NP).pass_arg(A(k)) for each k (NP <= k < NA)

• O(k - NP).pass_nothing for each k (NA <= k < NP+NO)

• R.pass_rest(vec of A(k) for each k (NP+NO <= k < NA))

事前条件

Rhsはvecでなければならない。

:CONTROL.require_from('kink/')

[:X :Y] <- ['x' 'y']
stdout.print_line('X={} Y={}'.format(X.repr Y.repr))
# => X="x" Y="y"

[:X :Y :Z.opt :W.opt] <- ['x' 'y']
stdout.print_line('X={} Y={} Z={} W={}'.format(X.repr Y.repr Z.repr W.repr))
# => X="x" Y="y Z=[] W=[]"

[:X :Y :Z.opt :W.opt] <- ['x' 'y' 'z']
stdout.print_line('X={} Y={} Z={} W={}'.format(X.repr Y.repr Z.repr W.repr))
# => X="x" Y="y Z=["z"] W=[]"

[:X :Y :Z.opt :W.opt] <- ['x' 'y' 'z' 'w']
stdout.print_line('X={} Y={} Z={} W={}'.format(X.repr Y.repr Z.repr W.repr))
# => X="x" Y="y Z=["z"] W=["w"]"

[:X :Y :R.rest] <- ['x' 'y']
stdout.print_line('X={} Y={} R={}'.format(X.repr Y.repr R.repr))
# => X="x" Y="y" R=[]

[:X :Y :R.rest] <- ['x' 'y' 'r1' 'r2']
stdout.print_line('X={} Y={} R={}'.format(X.repr Y.repr R.repr))
# => X="x" Y="y" R=["r1" "r2"]

[:X :Y :Z.opt :W.opt :R.rest] <- ['x' 'y']
stdout.print_line('X={} Y={} Z={} W={} R={}'.format(X.repr Y.repr Z.repr W.repr R.repr))
# => X="x" Y="y" Z=[] W=[] R=[]

[:X :Y :Z.opt :W.opt :R.rest] <- ['x' 'y' 'z']
stdout.print_line('X={} Y={} Z={} W={} R={}'.format(X.repr Y.repr Z.repr W.repr R.repr))
# => X="x" Y="y" Z=["z"] W=[] R=[]

[:X :Y :Z.opt :W.opt :R.rest] <- ['x' 'y' 'z' 'w']
stdout.print_line('X={} Y={} Z={} W={} R={}'.format(X.repr Y.repr Z.repr W.repr R.repr))
# => X="x" Y="y" Z=["z"] W=["w"] R=[]

[:X :Y :Z.opt :W.opt :R.rest] <- ['x' 'y' 'z' 'w' 'r1' 'r2']
stdout.print_line('X={} Y={} Z={} W={} R={}'.format(X.repr Y.repr Z.repr W.repr R.repr))
# => X="x" Y="y" Z=["z"] W=["w"] R=["r1" "r2"]

# Invalid numbers of right-hand-side vals:
CONTROL.try(
  { [:X :Y] <- [1 2 3] }
  { raise('must not reach here') }
  {(:Exc)
    stdout.print_line('exception: {}'.format(Exc.message))
  }
)
# => exception: too many args: for [:X :Y], got [1 2 3]

CONTROL.try(
  { [:X :Y] <- [1] }
  { raise('must not reach here') }
  {(:Exc)
    stdout.print_line('exception: {}'.format(Exc.message))
  }
)
# => exception: too few args: for [:X :Y], got [1]

6.27.1.48. Vec.repr

reprは、Vecのstr表現を戻す。

stdout.print_line(['foo' 42].repr)  # => ["foo" 42]

6.27.2. VEC.is?(Val)

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

6.27.3. VEC.from_each(Eacher)

from_eachは、Eacherの要素をすべて含むvecを新しく作って戻す。

Eacherは、.each($consume)メソッドを持っていなければならない。eachは、それぞれの要素について$consumeを呼び出すものでなければならない。

:VEC.require_from('kink/')
:FLAT_SET.require_from('kink/container/')

:Set <- FLAT_SET.of('foo' 'bar' 'baz')
stdout.print_line(VEC.from_each(Set).repr)
# => ["bar" "baz" "foo"]