このエントリはPerl Advent Calendar 2024の22日目のエントリとなります。
他の言語にあるアレとは
皆さん、Perl触ってますか?Perlを触っている方もそうでない方も、ご自身がよく使う言語にあるメジャーなライブラリや大変有用な基礎機能というものがあると思います。私が思いつくところですと、例えば以下のようなものでしょうか。
- C#におけるLINQ
 - F#におけるパイプライン演算子
 - Goにおけるgoroutine
 - RubyにおけるMix-in
 - ElixirにおけるLiveView
 - PHP/LaravelにおけるLivewire
 - などなど・・・
 
とにかく、いくつかの言語で実装されている便利なやつ、ということを言いたいのです。
で、最近私はTypescriptという言語を触る機会が多いのですが、この言語では大変有用なライブラリがたくさん作られ、提供されています。一部をご紹介します。
- Prisma ORM : Typescript向けに作られたORM。スキーマ変更に対するケアが素晴らしい。
 - Zod : データバリデーター。非常に複雑なデータ構造に対するスキーマをシンプルに記述できる。
 - Biome : ソースコードのフォーマッティングと構文解析を行うツール。品質の高いコードには必須。
 
Perlにも便利なものを持ってきてもいいじゃないか
近ごろは、Perlにとって明るい話題というのをなかなか聞かなくなってきたなぁと思うようになりました。個人的にはPerlは好きな言語ですし、私がまともにITエンジニアとして食っていけるようになるきっかけとなった言語ですので、末永く便利に使いたいものだと思っています。
そんなことを考えていたある日、先ほどご紹介したZodというバリデーターの存在を知り、業務でも利用するようになりました。このZodの便利なところは、とにかくスキーマを細やかに指定できるというところであり、そのスキーマ自体が変数として取り扱うことが出来る点です。
例えばご当地バーガーショップのレシートデータを構造化しようと考えた場合、そのデータスキーマを設計する必要があります。注文された商品とその点数、テーブル番号、値段などがデータスキーマに含まれる必要があることでしょう。
Zodで表現するならば、だいたい以下のようになるかと思います。
1  | import { z } from 'zod'  | 
こういう感じのスキーマ定義を、型がとても緩いPerlでも使えるようにしたら便利では?と思い、移植してみました。それが拙作のCPANライブラリであるPozです。
Pozのつかいかた
Pozをインストールする場合は cpanm などのPerlモジュール管理ツールをお使いいただくのが最も簡単です。
1  | $ cpanm Poz  | 
では、先ほどZodで表現してみたご当地バーガーショップのレシートデータ構造化スキーマを、Pozでもやってみます。
1  | use strict;  | 
なるべくインターフェースをZodに寄せてありますので、ほぼZodの使い方と一緒です。
違うとことがあるとすれば、 ->as('BurgerShop::Receipt') のあたりでしょうか。これは本家Zodにはない指定でして、Zodの場合は構造体の型を z.infer で生成することができるのですが、Perlの場合はHashRefに型を紐づけたい場合、blessするほかありません。
そのような言語の特性を吸収するべく、バリデーションが通ったHashRefについては as(...) で指定したクラスのオブジェクトとしてblessしてしまおう、という対応をとっています。
なお、実際にバリデーションを行うときには以下のようにします。
1  | my $data = {  | 
上記の例では safe_parse を使っていますが、本家Zodと同じように parse も使えます。ここら辺のインターフェースもZodによせてありますので、Zodに慣れている方であれば違和感なくご利用いただけるのではないでしょうか。
なお、この時以下のテストが通ります(実はこのエントリを書いていてバグに気が付いたので、急いで直して、v0.03をリリースしました・・・!!)
1  | # エラーは無し  | 
まあまあ複雑なデータ構造もいい感じに検証されており、無事に検証を通過したデータは適切にblessされているのがわかります。ちょっと頑張りましたね!
kuraとの連携
Perlの型ライブラリに kura というものがございまして、これはMetaCPANにある様々な型ライブラリのうち、 Data::Checks, Type::Tiny, Moose::Meta::TypeConstraint, Mouse::Meta::TypeConstraint, Specio などを横断的に使えるようにしてしまおうという、大変意欲的なものとなっています。
なんと、ありがたいことに、kuraの作者である こばけんさん からPozにコントリビュートをいただいており、 既にkuraとの連携 ができるように調整いただいております。本当にありがたいことです。
1  | use Poz qw(z);  | 
というか、Pozをリリースしてから2日以内くらい?でこれが出来るようになっていたんです。すごくないですか・・・?
まとめ
ZodをPerlに移植したようなバリデーター「Poz」を作った話をさせていただきました。
別の言語で使える便利そうなやつをPerlに持ってくるというのは、かなり楽しいです。
今のご時世、AIによるサポートを得ながらライブラリの開発ができますが、今回作ったPozもGitHub Copilotを存分に活用して開発しました。なかなか簡単に作れたので、ちょっとPerlに元気を与えたいと思った方にはぜひともチャレンジしてもらいたいなと思います。