てきとうなさいと べぇたばん

PHP 8.4でgrapheme_str_split関数を追加しました #phpcondo

TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > PHP 8.4でgrapheme_str_split関数を追加しました #phpcondo

PHPカンファレンス北海道2024で発表した提案の内容を反映できた

grapheme_str_split関数を追加しました

「str_split、そういえば書記素クラスター単位のstr_splitないよな?」とPHPカンファレンス北海道2024で発表資料を作って気付いてから4ヶ月。ついにgrapheme_str_split関数がmasterブランチにマージされ、日の目を見ました。

https://wiki.php.net/rfc/grapheme_str_split

概要

書記素クラスターとはなにか?というところから話をしなければいけませんが、例えばこの🙇‍♂️男性が土下座をしている絵文字は、1文字に見えると思います。 見えなかったらお使いのデバイスのOSか何かが古すぎます。この、「1文字に見える」というものを「書記素クラスター(Grapheme cluster)」と呼んでいます。

しかし、実は🙇‍♂️はコードポイント(Unicodeのコードポイント)単位では4つのコードポイントで構成されています。mb_str_splitをすればそれがなにの意味をなしているのかわかります。

$ sapi/cli/php -r 'var_dump(mb_str_split("🙇‍♂️"));' array(4) { [0]=> string(4) "🙇" [1]=> string(3) "‍" // U+200D Zero Width Joinner [2]=> string(3) "♂" [3]=> string(3) "️" // U+FE0F VARIATION SELECTOR }

これではstr_splitできないじゃん!と気付いたといいますか、そもそもGrapheme関数の内容が少なすぎると感じました。 したがって、少なくともstr_split出来たほうがよくない?ということでgrapheme_str_splitを作るという運びになりました。

なお、他の言語では大体書記素クラスター単位で処理できるようにはなっていて、Rubyでは String#grapheme_clusters があります。

使い方

function grapheme_str_split(string $string, int $length = 1): array|false {}

使用例

$ sapi/cli/php -r 'var_dump(grapheme_str_split("👨🏻‍❤️‍💋‍👨🏾👩‍❤️‍👩"));' array(2) { [0]=> string(35) "👨🏻‍❤️‍💋‍👨🏾" [1]=> string(20) "👩‍❤️‍👩" }

$stringにはUTF-8のみ許可しています。$lengthには配列の1要素に何文字いれる?というものです。内部で処理に失敗することがある場合にfalseが返ります。通常は配列が返ってきます。 Intl拡張なので --enable-intl でいれることをお忘れなく。

感想

このRFCは結構人気だったっぽくて、最終的には19票のYesをいただきました。それだけUnicodeに興味を持ってもらえたのは幸いだったと思います。また、ここでは述べていませんが、異体字セレクタにも適用できるわけですが、漢字の異体字セレクタだけでは難しかったかもしれません。絵文字ありがとう。

2024/04/11 20:39