なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

正規表現を関数オブジェクトにしてandThenで連結してみる

関数オブジェクトと関数合成を使うとなんか便利になることもあるという記事のつもり

Scala Advent Calendar 2015 20日目の @Hiroyuki-Nagata です.
前の人は @gakuzzzzさん,次の人は @ishi_kuroさん です.
www.adventar.org

andThenを使ってみる

ScalaにはcomposeやandThenという関数オブジェクトをまとめるメソッドがあります。事前に使いたい関数を関数オブジェクトの形にしておくと何も考えずに合成できるのでよいです。

composeとandThenの日本語の説明は以下
Scala 関数メモ(Hishidama's Scala Function Memo)

// このように定義すると、funcCはfuncAを行った後funcBを実行する処理になる
val funcC = funcA.andThen(funcB)

実際に文字を書き換える処理を入れてみる

object prog {

    val funcA = (str: String) =>
    str.replace("A", "B")

    val funcB = (str: String) =>
    str.replace("B", "C")

    val funcC = funcA.andThen(funcB)

    def main(args: Array[String]) = {
        println(funcC("ABC"))
    }
}

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
funcAは文字列に"A"があれば"B"に書き換え、funcBは"B"があれば"C"に書き換えるだけです。

実行結果

Start
CCC
0
Finish
正規表現を使ってみる

Scala正規表現使う時は、先に正規表現を定義しておいてそれをパターンマッチに通すのが簡単です。

    // Perl的なsubで始まり中括弧があればマッチ
    val func = """(.*:?)sub(.*:?)\{(.*)$""".r

    val replaceFunc = (perl: String) =>
    perl match {
        case func(head, funcName, tail) =>
            // Scala的なdefで始まるメソッドに書き換える
            s"${head}def${funcName}() = {${tail}"
        case _ =>
            perl
    }
正規表現を関数合成でまとめてみる

全ソースは以下に貼り付けました
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

着目するのは以下の.andThen。このようにすれば雑ですがいくらでも関数が連結できる。

    val replaceExample = replaceAtMark
        .andThen(replaceFunc)
        .andThen(replaceDefDollarMark)


と、以上です。普通のオブジェクト指向言語だと、リファクタリングのために関数の編成を行う時に関数が関数を呼び出す形にすると読みにくくなってしまいます。andThencomposeを使うとそのへん機械的にわかりやすく書けるような気がしました。まあそれだけならメソッドチェーン有るじゃんと言われるかもしれませんが。
お粗末さまでした。