aiscript icon indicating copy to clipboard operation
aiscript copied to clipboard

codepoint_atで下位サロゲートが残っている

Open FineArchs opened this issue 1 year ago • 18 comments

expected behaviour

let char = "𩸽" 
<: s.codepoint_at(0) // 171581
<: s.codepoint_at(1) // null

actual behaviour

let char = "𩸽" 
<: s.codepoint_at(0) // 171581
<: s.codepoint_at(1) // 56893

FineArchs avatar Feb 09 '24 08:02 FineArchs

@MineCake147E 👀

FineArchs avatar Feb 09 '24 08:02 FineArchs

codepoint_atのインデックスは16bit単位なので、下位サロゲートの位置を直接指定した場合は下位サロゲートを返します。

MineCake147E avatar Feb 09 '24 08:02 MineCake147E

あー、JavaScriptのcodePointAtがその仕様なんですね ただAiScriptにはcharcode_atもあることを考えると、codepoint_atはサロゲートペア単位にした方が用途が多いと思います

FineArchs avatar Feb 09 '24 09:02 FineArchs

to_unicode_arrto_unicode_codepoint_arrがコードポイントごとに区切るので、その用途ではそれをご利用ください。

<: `{'𩸽👉🏿👨‍👦'.to_unicode_arr()}`
<: `{'𩸽👉🏿👨‍👦'.to_unicode_codepoint_arr()}`
str [ "𩸽", "👉", "🏿", "👨", "‍", "👦" ]
str [ 171581, 128073, 127999, 128104, 8205, 128102 ]
(null)

こちらの方が、毎回分割するよりはパフォーマンス的にも良いかと思います。

MineCake147E avatar Feb 09 '24 10:02 MineCake147E

仕様の形としては直感的でないですが、パフォーマンス的には確かにそうですね…

FineArchs avatar Feb 09 '24 14:02 FineArchs

codepoint_atでindexをコードポイント単位にはできないですかね?(ある程度パフォーマンスを維持しながら) もしできなさそうであれば、代替の方法もあるわけなのでこのAPIはあまり必要ない気がします。

marihachi avatar Feb 11 '24 02:02 marihachi

codepoint_atでindexをコードポイント単位にはできないですかね?(ある程度パフォーマンスを維持しながら)

出来なくはないかもしれませんが、互換性等を考慮すると、オプション引数を新設する必要があると思います。 毎回to_unicode_arr相当の処理を行うのは無駄が多いため現在の仕様となっています。(indexが0の場合だけ特殊対応をしてもいいかもしれませんが…)

もしできなさそうであれば、代替の方法もあるわけなのでこのAPIはあまり必要ない気がします。

to_unicode_arrしたものから一文字分のコードポイントを取得する際に必要になります。 毎回to_unicode_codepoint_arrを実行すると、毎回配列を返すことになり無駄が多いため、codepoint_atは結局必要だと思います。

MineCake147E avatar Feb 11 '24 03:02 MineCake147E

一文字からコードポイントの取得はこの関数しかないんですね... あとは、1文字にto_unicode_codepoint_arrして0番目を取りだすという方法もある?

marihachi avatar Feb 11 '24 06:02 marihachi

1文字からコードポイントを取得する関数があってもよさそうです。 それならcodepoint_atがなくても良いですよね?

marihachi avatar Feb 11 '24 06:02 marihachi

codepoint_at(0)を専用の関数にするということでよろしいですか?

MineCake147E avatar Feb 11 '24 06:02 MineCake147E

  1. 文字列をコードポイントの情報を元に文字やコードポイントに分割する
  2. 分割された文字を必要に応じてコードポイントに変換する

この流れでAPIを利用できれば十分だと思います

marihachi avatar Feb 11 '24 07:02 marihachi

それだと機能が減るだけで変更のメリットが何もないような気がしますが…

FineArchs avatar Feb 11 '24 12:02 FineArchs

codepoint_atの下位サロゲートが残る問題はjsの仕様で仕方ないですけど、codepoint_atが無くなればその問題は解消されますね

marihachi avatar Feb 12 '24 00:02 marihachi

直感的でない部分が排除されることで、API全体の分かりやすさは向上すると思います。

marihachi avatar Feb 12 '24 00:02 marihachi

少し話が変わりますが jsが内部的にUTF-16で文字列を保持してるためインデックスもUTF-16コード単位になってると思うので、 AiScriptではコードポイントの配列を文字列の内部表現にするのもアリな気がしました。 コードポイント単位で文字が保持されているならcodepoint_atもうまく実装できそうです。 他のAPIはいろいろ検討する必要がありそうなので分かりませんが。

marihachi avatar Feb 12 '24 00:02 marihachi

直感的でない部分が排除されることで、API全体の分かりやすさは向上すると思います。

うーんまあ確かにそうかもです

AiScriptではコードポイントの配列を文字列の内部表現にするのもアリな気がしました。

今の実装だと文字列処理では内部的にはJavaScriptの文字列をそのまま使っている訳ですが、それらを全部独自実装に置き換える感じですか?

FineArchs avatar Feb 12 '24 09:02 FineArchs

今の実装だと文字列処理では内部的にはJavaScriptの文字列をそのまま使っている訳ですが、それらを全部独自実装に置き換える感じですか?

独自実装といえばそうですね。 文字列からコードポイントの配列、コードポイントの配列から文字列への変換は、今でもやってるようにjsの機能で可能だと思うので、AiScriptのインタプリタが文字列を保持するときにはコードポイントの配列に変換しておくというイメージです。

marihachi avatar Feb 12 '24 12:02 marihachi

毎回変換すると重くなりそうなので両方保持しておきたい気もします キャッシュみたいに必要次第で持っておくのもいいかも

FineArchs avatar Feb 13 '24 08:02 FineArchs