30
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHPにパターンマッチングはないが… 作ればいいよ

Posted at

PHPではいわゆるパターンマッチングはできません。

PHP 8.0で導入されたmatchは「ちゃんとした」パターンマッチじゃないんだってRFCに書いてあったよ。

うーん… 困った。そうだね、ないなら作ろう。

$result = match (ing($subject, matcher: $_, matched: $m)) {
    $_(is: 'ほげ') => 'これはほげだよ',
    $_(class: DateTime::class) => "これはDateTimeだよ",
    $_([$_->a]) => "要素1 マッチしたよ! {$m->a}",
    $_([$_->a, $_->b]) => "要素2 マッチしたよ! {$m->a} {$m->b}",
    $_([$_->a, $_->b, $_->c]) => "要素3 マッチしたよ! {$m->a}, {$m->b}, {$m->c}",
    $_(['config' => ['password' => $_->pass]]) => "password = {$m->pass}",
    $_('/\A〒?(?<up>[0-9]{3})-(?<down>[0-9]{4})\z/u') => "郵便番号は{$m->up}{$m->down}だよ!",
    $_(is_string(...)) => "これは文字列($m->value)だよ",
    $_(is_int(...)) => "これは整数($m->value)だよ",
    $_(is_float(...)) => "これは浮動小数点数($m->value)だよ",
    default => 'not matched',
};

実装したもの

  • is:マッチャー
    • === で比較するやつ
    • 普通のmatchの条件節と同じだけど、PHPのmatchの仕様上普通のマッチングは使えなくなるので仕方なく用意したよ
  • class:マッチャー
    • instanceofでチェックするやつ
  • 配列マッチャー
    • 配列の要素が一致しているかをチェックするやつ
    • 配列の中身から値をとりたいときは$_->hogeみたいに書くよ
      • マッチした後から$m->hogeでとれるよ
    • 入れ子になっても動くよ
  • 正規表現マッチャー
    • 文字列をpreg_matchでマッチさせるよ
      • マッチした内容は$m->でとれるよ

実装してないもの

  • 配列の残りの部分をぐいってまとめてとってくるやつとか
  • オブジェクトのプロパティを解体するやつとか
  • その他いろいろ

ちゃんとしたパターンマッチって何…? うん、よくわかんない。

コードはどこにあるの

ここにあります。説明は飽きたので各自コードを読んでください。

ライセンスはNYSLWTFPLのデュアルライセンスです。自由に改造して遊んでね。

このコードがどうして動くのかわからないんだけど

PHPのリファレンス(参照&)の傾向と対策、あるいはさよならを読んでください。

なんでこんな記事を…?

PHPのパターンマッチで遊んでみたに影響を受けました。

出来心でやってみたくなった縛りゲーシリーズ

アロー関数で無名再帰して書いたスターリンソート

そろそろ寝ます。おやすみなさい。

30
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?