6.23. kink/STR

6.23.1. str 型

str は有限長の不変なUnicodeコードポイントの文字列である。

Unicodeコードポイントについては右記を参照: https://www.unicode.org/versions/Unicode17.0.0/core-spec/chapter-3/#G22700

サロゲートコードポイント

str はサロゲートコードポイントを含むかもしれないが、その扱いはランタイムの実装に依存する。

たとえば、コードポイントが16ビットのコードユニットでエンコードされている場合、対になったサロゲートコードポイントは、BMP外のコードポイントにマージされるかもしれない。

:STR.require_from('kink/')

:Str <- STR.from_codepoints([0xd800 0xdc00])
stdout.print_line(Str.codepoints.repr)  # => [65536]

6.23.1.1. Str.codepoints

codepoints は Str のコードポイントを含む vec を戻す。

stdout.print_line('xyz'.codepoints.repr) # => [120 121 122]

6.23.1.2. Str.size

size は Str のコードポイントの数を整数の num として戻す。

6.23.1.3. Str.any?

any?はStrが1個以上のコードポイントを含んでいるかどうかを戻す。

6.23.1.4. Str.get(Codepoint_ind)

get は Codepoint_ind の位置のコードポイントを戻す。

結果はコードポイントを表す整数の num だ。

事前条件

Codepoint_ind は、 [0, Str.size - 1] の範囲に含まれる整数の num でなければならない。

stdout.print_line('xyz'.get(0).repr) # => 120

6.23.1.5. Str.slice(From To)

sliceは、Strのスライスを作ってstr値として戻す。

スライスは、[From, To)の範囲のコードポイントからなる。結果のstrは、(To - From)個のコードポイントを持つ。

事前条件

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

0 <= From <= To <= Str.size

:Str <- 'foobar'
:Slice <- Str.slice(1 4)
stdout.print_line(Slice.repr) # => "oob"

6.23.1.6. Str.take_front(N)

take_front は Str の最初の N 個のコードポイントを含む str を戻す。

事前条件

N は[0, Str.size]の範囲に含まれる整数の num でなければならない

stdout.print_line('foobar'.take_front(2).repr)  # => "fo"

6.23.1.7. Str.take_back(N)

take_back は Str の最後の N 個のコードポイントを含む str を戻す。

事前条件

N は[0, Str.size]の範囲に含まれる整数の num でなければならない

stdout.print_line('foobar'.take_back(2).repr)  # => "ar"

6.23.1.8. Str.drop_front(N)

drop_front は Str から最初の N 個のコードポイントを除いた str を戻す。

事前条件

N は[0, Str.size]の範囲に含まれる整数の num でなければならない

stdout.print_line('foobar'.drop_front(2).repr)  # => "obar"

6.23.1.9. Str.drop_back(N)

drop_back は Str の最後の N 個のコードポイントを除いた str を戻す。

事前条件

N は[0, Str.size]の範囲に含まれる整数の num でなければならない

stdout.print_line('foobar'.drop_back(2).repr)  # => "foob"

6.23.1.10. Str.search_slice(Slice Min_pos ...[$config={}])

search_slice は Str の中でスライスを探す。探索をコードポイントの添字 Min_pos から始めて、見つかったスライスが始まるコードポイントの添字である Pos を出力する。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity.

• C.on_error($error): default = 例外を投げる関数

search_slice は、 Pos >= Min_pos と Str.slice(Pos Slice.size) == Slice を満たす最も小さい Pos を探す。もしそのような Pos が見つかれば、 search_slice は $success を、 Pos を引数として末尾呼び出しする。もし見つからなければ、 search_slice は $error を引数なしで末尾呼び出しする。

事前条件

Slice は str 型でなければならない。

Min_pos は [0, Str.size] の範囲の整数の num でなければならない。

$success は整数の num を取る関数でなければならない。

$error はパラメータなしの関数でなければならない。

stdout.print_line('foofoo'.search_slice('oo' 0).repr) # => 1
stdout.print_line('foofoo'.search_slice('oo' 1).repr) # => 1
stdout.print_line('foofoo'.search_slice('oo' 2).repr) # => 4

'foofoo'.search_slice('oo' 5)
# Output:
#   -- main exception
#   ,,,
#   Str.search_slice(Slice Min_pos ...[$config]): slice not found

:attempt_search <- {(:Str :Min_pos :Slice)
  Str.search_slice(Slice Min_pos){(:C)
    C.on_success{(:Pos)
      stdout.print_line('found at: {}'.format(Pos.repr))
    }
    C.on_error{
      stdout.print_line('not found')
    }
  }
}
attempt_search('foofoo' 0 'oo')  # => found at: 1
attempt_search('foofoo' 1 'oo')  # => found at: 1
attempt_search('foofoo' 2 'oo')  # => found at: 4
attempt_search('foofoo' 3 'oo')  # => found at: 4
attempt_search('foofoo' 4 'oo')  # => found at: 4
attempt_search('foofoo' 5 'oo')  # => not found
attempt_search('foofoo' 6 'oo')  # => not found

6.23.1.11. Str.have_prefix?(Prefix)

have_prefix? はStr の先頭が Prefix かどうかを戻す。

Str.take_front(Prefix.size) が Prefix に等しいとき、 have_prefix? はtrueを戻す。そうでなければ、 have_prefix? はfalseを戻す。

事前条件

Prefix は str 型でなければならない。

6.23.1.12. Str.have_suffix?(Suffix)

have_suffix? は Str の末尾が Suffix かどうかを戻す。

Str.take_back(Prefix.size) が Suffix に等しいとき、 have_suffix?? はtrueを戻す。そうでなければ、 have_suffix? はfalseを戻す。

事前条件

Suffix は str 型でなければならない。

6.23.1.13. Str.have_slice?(Slice)

have_slice? は Str が Slice をスライスとして持っているかどうかを戻す。

もし Str.slice(Ind Ind + Slice.size) が Slice と等しいような Ind があれば、 have_slice? はtrueを戻す。なければ、 have_slice? はfalseを戻す。

事前条件

Slice は str 型でなければならない。

6.23.1.14. Str.trim

trim は Str の先頭と末尾から空白類の文字を取り除いたスライスを戻す。

trim は Str のスライスのうち、空白類の文字で始まらず、空白類の文字で終わらない最長のスライスを戻す。

空白類の文字は、[U+0000, U+0020]の範囲内のコードポイント、あるいはU+007fである。

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim.repr) # => "foobar"
stdout.print_line(" \t\r\n\n\r\t ".trim.repr)       # => ""

6.23.1.15. Str.trim_front

trim_front は Str の先頭から空白類の文字を取り除いたスライスを戻す。

trim_front は Str のスライスのうち、空白類の文字で始まらない最長のスライスを戻す。

空白類の文字の定義は trim を見よ。

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim_front.repr) # => "foobar\n\r\t "
stdout.print_line(" \t\r\n\n\r\t ".trim_front.repr)       # => ""

6.23.1.16. Str.trim_back

trim_back は Str の末尾から空白類の文字を取り除いたスライスを戻す。

trim_back は Str のスライスのうち、空白類の文字で終わらない最長のスライスを戻す。

空白類の文字の定義は trim を見よ。

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim_back.repr) # => " \t\r\nfoobar"
stdout.print_line(" \t\r\n\n\r\t ".trim_back.repr)       # => ""

6.23.1.17. Str.ascii_upcase

ascii_upcase は、 Str 中のASCII小文字のコードポイント(U+0061='a' から U+007A='z')を、対応するASCII大文字(U+0041='A' から U+005A='Z')に変換する。

ascii_upcase は、ASCII小文字以外のコードポイントを変換しない。

stdout.print_line('Azkaban'.ascii_upcase.repr) # => "AZKABAN"
stdout.print_line('+-*/%<>'.ascii_upcase.repr) # => "+-*/%<>"
stdout.print_line('Товарищ'.ascii_upcase.repr) # => "Товарищ"

6.23.1.18. Str.ascii_downcase

ascii_downcase は、 Str 中のASCII大文字のコードポイント(U+0041='A' から U+005A='Z')を、対応するASCII小文字(U+0061='a' から U+007A='z')に変換する。

ascii_downcase はASCII大文字以外のコードポイントを変換しない。

stdout.print_line('aZKABAN'.ascii_downcase.repr)  # => "azkaban"
stdout.print_line('+-*/%<>'.ascii_downcase.repr)  # => "+-*/%<>"
stdout.print_line('Товарищ'.ascii_downcase.repr)  # => "Товарищ"

6.23.1.19. Str.format(... Args) / Str.format($config)

format は、 Str をテンプレートとして str を生成する。

format にはふたつのオーバーロードがある。

オーバーロード: Str.format(... Args)

可変長の引数 Args が渡されたとき、 format は Args の各要素を位置引数として使う。

事前条件:

• Str は下記する文法を満たす str でなければならない。

• Args の各要素は show メソッドを持っていなければならない。

オーバーロード: Str.format($config)

$config関数が渡されたとき、 format は$configをコンフィグ関数として使う。

事前条件:

• Str は下記する文法を満たす str でなければならない。

• $configは format_config を引数として取る関数でなければならない。

テンプレート文字列の書式

テンプレート文字列には、波括弧 "{" と "}" で区切られたプレースホルダを含められる。 format はプレースホルダに対応する引数について、 .show(...[$config]) メソッドを呼び、その結果の文字列をプレースホルダの場所に埋め込む。

プレースホルダには次の変種がある。

• "{}": 位置引数を取り、空文字列 "" を指示子とする。

• "{%xxx}": 位置引数を取り、 "xxx" を指示子とする。

• "{Foo}": "Foo" という名前の名前引数を取り、空文字列 "" を指示子とする。

• "{Foo%xxx}": "Foo" という名前の名前引数を取り、 "xxx" を指示子とする。

名前には "{", "}", "%" が含められない。

指示子は Show_config.spec(Spec) メソッドに渡される。指示子には "{", "}" が含められない。

テンプレート文字列に "{" と "}" を含めたい場合、 "{{", "}}" としてエスケープする。

stdout.print_line('{} == 0x{%04x}'.format(42 42))
# => 42 == 0x002a

stdout.print_line('{}: message: {}'.format('WARN' 'something went wrong'))
# => WARN: message: something went wrong

ロケールを指定:

:LOCALE.require_from('kink/')

:Str <- 'Id: {%04d}, Name: {}, Elevation: {%,d} meters'.format{(:C)
  C.locale(LOCALE.for('da-DK'))
  C.arg(12)
  C.arg('Mount Fuji')
  C.arg(3776.24)
}
stdout.print_line(Str)
# => Id: 0012, Name: Mount Fuji, Elevation: 3.776,24 meters

名前引数を使う:

:LOCALE.require_from('kink/')

:Str <- 'Id: {Id%04d}, Name: {Name}, Elevation: {Elevation%,d} meters'.format{(:C)
  C.locale(LOCALE.for('da-DK'))
  C.named_arg('Id' 12)
  C.named_arg('Name' 'Mount Fuji')
  C.named_arg('Elevation' 3776.24)
}
stdout.print_line(Str)
# => Id: 0012, Name: Mount Fuji, Elevation: 3.776,24 meters

6.23.1.20. Str1 + Str2

+ 演算子、つまりop_addメソッドは、Str1のコードポイント列を前に、Str2のコードポイント列を後ろに配した文字列を戻す。

事前条件

Str は str 型でなければならない

:Str <- 'foo' + 'bar'
stdout.print_line(Str.repr) # => "foobar"

6.23.1.21. Str * N

* 演算子、つまりop_mulメソッドは、StrをN回繰り返した文字列を戻す。

事前条件

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

stdout.print_line(('foo' * 0).repr) # => ""
stdout.print_line(('foo' * 1).repr) # => "foo"
stdout.print_line(('foo' * 2).repr) # => "foofoo"
stdout.print_line(('foo' * 3).repr) # => "foofoofoo"

6.23.1.22. Str1 == Str2

== 演算子、つまりop_eqメソッドは、ふたつの文字列が同じコードポイントの列から成っているかどうかを戻す。

事前条件

Str1 と Str2 は str 型でなければならない。

stdout.print_line(('foo' == 'foo').repr)  # => true
stdout.print_line(('foo' != 'foo').repr)  # => false

stdout.print_line(('foo' == 'FOO').repr)  # => false
stdout.print_line(('foo' != 'FOO').repr)  # => true

6.23.1.23. Str1 <= Str2

<= 演算子、つまりop_leメソッドは、ふたつの文字列のコードポイントを辞書順で比較し、Str1がStr2以下かどうかを戻す。比較はUnicodeのコードポイントの大小関係に従って、先頭から末尾にかけて行われる。

比較の結果は java.lang.String.compareTo と異なり得ることに注意しよう。これは、String.compareToが文字列の比較を16ビットのコードユニットを元に行うためだ。

事前条件

Str2はstr型でなければならない

stdout.print_line(('fo' <= 'foo').repr)   # => true
stdout.print_line(('foo' <= 'foo').repr)  # => true
stdout.print_line(('fooo' <= 'foo').repr) # => false
stdout.print_line(("\x{ffff}" <= "\x{10000}").repr) # => true

6.23.1.24. Str.show(...[$config={}])

show は Str 自体を戻す。

show は省略可能なパラメータ$configを取れるが、これが呼ばることはない。

.showメソッドの一般的な契約については、この記事中の *.show(...[$config]) を見よ。

stdout.print_line('xyz'.show)
# Output:
#   xyz

stdout.print_line('xyz'.show{})
# Output:
#   xyz

stdout.print_line("foo\nbar".show)
# Output:
#   foo
#   bar

6.23.1.25. Str.repr

repr は Str のデバッグ用の文字列表現を戻す。

stdout.print_line('xyz'.repr)       # => "xyz"
stdout.print_line("foo\nbar".repr)  # => "foo\nbar"

6.23.2. format_config 型

format_config は Str.format のコンフィグ値である。

6.23.2.1. Format_config.arg(Pos_arg)

arg メソッドは位置引数を追加する。

arg メソッドの呼び出し回数は、名前のないプレースホルダの数と同じでなければならない。

事前条件

Pos_arg は .show(...[$config]) メソッドを提供しなければならない。

6.23.2.2. Format_config.named_arg(Name Arg)

named_arg メソッドは名前引数を追加する。

テンプレート文字列中で参照されない Name を渡しても構わない。

事前条件

Name は空でない str である必要がある。また、正規表現 [a-zA-Z_][a-zA-Z0-9_?]* に受け入れられる必要がある。

Arg は .show(...[$config]) メソッドを提供しなければならない。

Name1, Name2, ,,, の集合は、テンプレート中の名前引数の名前の集合の上位集合でなければならない。

stdout.print_line('X={X}, Y={Y}'.format{(:C)
    C.named_arg('X' 10)
    C.named_arg('Y' 20)
    C.named_arg('Z' 30) # Z is not in the template str, but it is OK
  }
)
# => X=10, Y=20

6.23.2.3. Format_config.locale(Locale)

locale メソッドはロケールを指定する。 Locale は各プレースホルダの show メソッドに渡される。

事前条件

Locale は locale 型でなければならない。

6.23.3. *.show(...[$config={}]) メソッド

この節では、任意の型の show メソッドについて一般的な契約を述べる。

show メソッドには、レシーバを表現する文字列を戻すことが期待される。 repr メソッドがデバッグメッセージに使われるのに対して、 show メソッドはUIメッセージに使われる。

通常、 show メソッドはStr.formatから呼ばれる。

コンフィグメソッド

• C.locale(Locale): default = Locale.root

• C.spec(Spec): default = ''

Locale は locale 型でなければならない。 show メソッドはロケールを用いて結果をローカライズできる。

Spec は str 型でなければならない。 show メソッドはこの指示子を用いて結果を調整できる。指示子の文法は show メソッドの実装に依存するが、少なくとも show メソッドは空文字列 '' を指示子として受け取れなければならない。

例:

:LOCALE.require_from('kink/')
:Shown <- 3776.24.show{(:S)
  S.locale(LOCALE.for('da-DK'))
  S.spec(',d')
}
stdout.print_line(Shown.repr) # => "3.776,24"

show メソッドは上記以外のコンフィグメソッドも提供できる。たとえば、Num.showは radix と pad_zero というコンフィグメソッドを提供する:

:Shown <- 255.show{(:S)
  S.radix(16)
  S.pad_zero(4)
}
stdout.print_line(Shown.repr) # => "00ff"

6.23.4. STR.is?(Val)

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

6.23.5. STR.from_codepoints(Codepoints)

from_codepoints は指定されたコードポイントを含む str を戻す。

事前条件

Codepoints は each メソッドを提供する列でなければならない。たとえば vec や iter など。

Codepoints の要素は [0x000000, 0x10ffff] の範囲の整数でなければならない。

:STR.require_from('kink/')
:Str <- STR.from_codepoints([120 121 122])
stdout.print_line(Str.repr) # => "xyz"

:ITER.require_from('kink/iter/')
:STR.require_from('kink/')
:Str <- STR.from_codepoints(ITER.of(120 121 122))
stdout.print_line(Str.repr) # => "xyz"

6.23.6. STR.default_newline

default_newline はランタイムのデフォルトの行区切りを戻す。

結果は str で、 "\r\n" か "\n" のどちらかである。