aiscript-dev / aiscript

🔋 A lightweight scripting language runing on JavaScript
https://aiscript-dev.github.io/ja/
MIT License
194 stars 34 forks source link

文字列とUnicodeに関する関数の拡充 Additional functions to manipulate string with Unicode code points #483

Closed MineCake147E closed 12 months ago

MineCake147E commented 1 year ago

概要

https://github.com/aiscript-dev/aiscript/pull/313str.codepoint_atが追加されましたが、何故かcharCodeAt()を呼び出しており、UTF-16の上位サロゲートをそのまま返してしまいます。 https://github.com/aiscript-dev/aiscript/blob/537fa96b3990fe55a7bebd1864f12ac87144b876/src/interpreter/primitive-props.ts#L77-L82 image 他、Unicodeコードポイントによる文字位置指定が現状できないことから、 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/@@iterator と同じことがAiScriptでも出来るようになったらいいなと思いました。 また、他にもいくつかの関数を提案します。

提案関数

str.unicode_codepoint_at(index)

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt str.codepoint_atとは違い、indexの位置の要素が UTF-16の上位サロゲートであった場合、そのサロゲートペアのコードポイントを返す。

"𩸽".unicode_codepoint_at(0) // 171581

戻り値はnum

str.to_arr()

AiScriptのstr.split()と同じ挙動をする。 書記素クラスタは保持される。

"𩸽👉🏿👨‍👦".to_arr() // ["𩸽", "👉🏿", "👨‍👦"]

戻り値はstrの配列。

str.to_unicode_arr()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/@@iterator と同じ挙動をする。 書記素クラスタは分割されるが、サロゲートペアは保持される。

"👉🏿".to_arr() // ['👉', '🏿']

戻り値はstrの配列。

str.to_unicode_codepoint_arr()

str.to_arr().map(@(a) {a.unicode_codepoint_at(0)})
'𩸽👉🏿👨‍👦'.to_unicode_codepoint_arr() // [171581, 128073, 127999, 128104, 8205, 128102]

戻り値はnumの配列。

str.to_char_arr()

JavaScriptのstring.split("")と同じ挙動をする。 サロゲートペアは分割される。 ※AiScriptのstr.split("")でもサロゲートペアは分割される

"😄".to_char_arr() // [55357, 56836].map(@(a) {Str:from_codepoint(a)})

str.to_charcode_arr()

str.codepoint_atをすべての文字に対して実行し、数値の配列を返す。 サロゲートペアは分割される。

"😄".to_charcode_arr() // [55357, 56836]

str.to_utf8_byte_arr()

文字列をUTF-8のバイト毎に分割し、数値の配列を返す。

"𩸽".to_utf8_byte_arr() // [240, 169, 184, 189]

Str:from_unicode_codepoints(array)

arr.map(@(a) {Str:from_codepoint(a)}).join()
Str:from_unicode_codepoints([171581, 128073, 127999, 128104, 8205, 128102]) // "𩸽👉🏿👨‍👦"

Str:from_utf8_bytes(array)

numarrを受け取り、UTF-8をデコードして文字列を作成する。

Str:from_utf8_bytes([240, 169, 184, 189]) // "𩸽"
marihachi commented 1 year ago

現行の関数の動作は修正したほうが良いかもです

marihachi commented 1 year ago

ユニコード非対応の関数を提供する必要があるのかというところですね

marihachi commented 1 year ago

あとは糖衣構文的な便利な組み込み関数を組み込み機能として入れるのかという部分も検討されるべきです

FineArchs commented 1 year ago

Unicodeについてあまりよく分かっていないのですが、例えば"👉🏿"はUnicodeのコードポイントでは一つの数字で表せるのですか?

ikasoba commented 1 year ago

str.codepoint_atは僕のミスですね 似た名前のメソッドがあっても混乱するだろうし、str.unicode_codepoint_atstr.codepoint_atに改名したほうが良さそう?

ikasoba commented 1 year ago

もし改名するなら、str.charcode_atも追加したほうが良さそうかな

MineCake147E commented 1 year ago

例えば"👉🏿"はUnicodeのコードポイントでは一つの数字で表せるのですか?

"👉🏿"は内部的には2文字です。U+1F449 WHITE RIGHT POINTING BACKHAND INDEXの後ろにU+1F3FF EMOJI MODIFIER FITZPATRICK TYPE-6が続いており、これらが一文字であるように表示されています。 また、"👨‍👦"は内部的には3文字です。(U+1F468 MAN + U+200D ZERO WIDTH JOINER + U+1F466 BOY) このように、複数文字のシーケンスを一文字として表示する「書記素クラスタ」(Grapheme Cluster)という概念がUnicodeには存在します。

MineCake147E commented 1 year ago

現行の関数の動作は修正したほうが良いかもです

現行ドキュメントとの矛盾を解決することを優先するならそれが良いと思います。

あとは糖衣構文的な便利な組み込み関数を組み込み機能として入れるのかという部分も検討されるべきです

恐らくstr.to_unicode_codepoint_arr()等についてのご意見だと思われますが、個人的にはMisskey Playのように実行速度制限がかかる状況においてAiScriptでやることは可能な限り減らしたいです。 Math内の関数の殆どがネイティブ実装されているのも同様の利点があると思います。

FineArchs commented 1 year ago

現行の関数の動作は修正したほうが良いかもです str.unicode_codepoint_atをstr.codepoint_atに改名したほうが良さそう?

賛成です。

FineArchs commented 1 year ago

to_arrは書記素クラスタ単位での分割を行う関数にしてほしいです。よりシンプルな名前の機能はより直観的であるべきです。 stringzに似た名前の関数があるので、それを利用するようにお願いします。

MineCake147E commented 1 year ago

to_arrは書記素クラスタ単位での分割を行う関数にしてほしいです。よりシンプルな名前の機能はより直観的であるべきです。

同様の機能はsplit()で既に存在しますが、確かにsplit()では分かりづらいかもしれませんね。

FineArchs commented 1 year ago

https://github.com/MineCake147E/aiscript/pull/1

@marihachi @saki-lere @syuilo 異論ある方はいますか?

FineArchs commented 1 year ago

@syuilo @saki-lere 認識合わせのため https://github.com/MineCake147E/aiscript/pull/1 について説明を加えておくと、

用語

現状

https://github.com/aiscript-dev/aiscript/pull/486

https://github.com/MineCake147E/aiscript/pull/1 ( #486 へのPR )

とりあえずこの2つのどちらを選ぶか決めたい感じです。