Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

string_randomをScalaでやる

string_random.jsというライブラリがある。正規表現を与えると、それを満たすような文字列を生成してくれる便利なやつだ。

デモページもある。

cho45.stfuawsc.com

f:id:Windymelt:20211126204856p:plain
おもしろい

このライブラリはjavascript用だが、正規表現を満たす文字列をいくつか生成したいという状況は普遍的であるから、こういうライブラリは様々な言語に欲しいところ。

Perl

metacpan.org

実はこちらが本家っぽいのだが、自分の中ではすっかりjavascriptのライブラリとして認識してしまっていた。どこ発祥なのか誰か教えてほしい。

Common Lisp

ちなみに自分が動かしているSlack用のbotにmelbotというのがいて、これは今のところCommon Lispで動いている。このbotにもその機能があって、string_random regexp?などと語り掛けると文字列をいくつか生成してくれる。ちなみにCommon Lisp用のstring_randomは無かったので自作した。

github.com

blog.3qe.us

Scalaでもやりたい

時代が下り、Scala 3がやってきた。Scala 3で動くmelbotも見てみたく、各機能を実装できるか眺めていると、Scala 3でも2系でも、そのものずばりのライブラリは残念なことに無いようだ。しかも難しいことに、標準ライブラリは正規表現のツリー構造を完全に隠蔽していて、リフレクションでも使わないことには、ツリーを辿って文字列生成するという従来の手法が使えない。困った困った。

そういうわけでいろいろ探しているうちに、antimirovという正規表現ライブラリに流れ着いた。もともとは正規表現を動的に生成するっぽいライブラリである。

このライブラリにはscalacheckやscalaprops用のバインディングが含まれており、プロパティテスト*1用の機能を流用することで、正規表現を満たす文字列を生成できる。

import antimirov.props.Regex

val r: Regex = Regex("[windymelt]{9}")
r.gen.samples(listSize = 10) // => List(elmimnynn, deyywmnen, ntlnnweee, ydwwiyiiy, llmdmddtn, nwtmmnwlw, eynmmmwii, iltynniey, nddmtwiii, wwdmtddwy)

けっこう拍子抜けに動いてしまった。たぶんライブラリの作者はこういう目的で使われるとは思っていなそうだが、大変ありがたい機能だ。元々テスト用機能なのでシード値を固定したりできるのが面白い。これでmelbotをscalaで実装できるかもしれない。

結論

  • ありがたいことに、antimirovライブラリとそのscalapropsバインディングを使うと、string_random.js同等の挙動を達成できる。

*1:「すべての整数」のように、考えられる入力を目的の処理にたくさん入力し、性質の保証を行う、証明とテストの中間的な機能

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?