doctree icon indicating copy to clipboard operation
doctree copied to clipboard

String#next の誤り

Open scivola opened this issue 4 years ago • 1 comments

https://docs.ruby-lang.org/ja/2.7.0/method/String/i/next.html

サンプルコードの最後の二つに問題があります。

p "\0".succ    # => "\001"
p "\377".succ  # => "\001\000"

おそらく Ruby 1.8 時代の記述が残っているのだと思います。 一つ目の "\0".succ はエンコーディング依存で,ASCII や CP932 であればサンプルコードとおりです。 UTF-8 などの Unicode 系の文字コードだと "\u0001" となります。

二つ目の "\377".succ(要するに "\0xFF".succ)ですが,ASCII-8BIT であればサンプルコードのとおりのようです。 (とりあえず Ruby 2.7.0 で試しています) ASCII や CP932 の場合 "\x01\xFF" になるようです。なぜこうなるのか理解できませんが。

p "\xFF".force_encoding("ASCII").succ # => "\x01\xFF"
p "\xFF".force_encoding("CP932").succ # => "\x01\xFF"

説明文の以下の記述も Ruby 1.8 時代のものかと思います。すべて間違っています。

  • self にアルファベットや数字とそれ以外の文字が混在している場合、アルファベットと数字だけが「次の」文字になり、残りは保存されます。
  • 逆に self がアルファベットや数字をまったく含まない場合は、単純に文字コードを 1 増やします。
  • このメソッドはマルチバイト文字を意識せず、単に文字列をバイト列として扱います。

以下は UTF-8 での実験です。

p "99".succ # => "100"
p "ん".succ # => "ゔ"

scivola avatar Feb 13 '20 22:02 scivola

0xFF の succ が ASCII や CP932 で不可解,という主旨のことを書きましたが,よく考えたら 0xFF というバイト列は ASCII や CP932 で valid encoding ではないのでした。

scivola avatar Feb 14 '20 03:02 scivola