readKotlinで言語内DSLを作ってビルダーとして提供してみる。Kotlinではコンストラクタ,関数へのデフォルト引数が許可されているため古典的なビルダーパターンは使うことが少ない。古典的なビルダーパターンはインスタンスの生成を安全に保ちつつ柔軟に構築できるようにするのを目標にしていた。ビルダーはオプショナルなチューニングパラメタを動的に受け入れ対象オブジェクトの生成を隠蔽する。対象オブジェクトのコンストラクタを事前条件の確認などに注力させ複雑な生成過程から分離させることができる。これは、たいてい他の言語でのデフォルト引数や名前付き引数に対する代替手段として使われる。コンストラクタ,関数へのデフォルト値や名前付き引数が提供されているKotlinでは、この用途でのビルダーパターンは使わない。柔軟な方法でオブジェクトを構築したくなったりする時がある。ビルド方法を隠蔽しつつ、欲しいオブジェクトの要件を定義する。するとオシャレに中置記法とか使いたくなったりする。なんだよみたいな感じだ。Kotlinでは出来てしまう。いうことでやってみる。言語内DSLが定義されたビルダークラスのスコープを準備して、スコープ関数(apply,with,run)経由で利用することにする。次の3つの事実を組み合わせる。キーワードを使うとメソッドに中置記法を許可することができる。クラススコープに対して拡張関数を定義できる。スコープ関数よりも追加処理が必要だったりするならスコープ関数も自分で定義すれば良い。いうわけで具体例を書いてみる。一部、悪い設計で書いてる。String)}使ってみるとこんな感じ。定義も呼び出しも、メモを残してる最中に雰囲気で書いてるため、細かいところで引っかかってコンパイラを通らないかも知れない。)}これをまともなコードって捉えるかは、やりたいことを上手く表してるかとか素朴な実装が難しいかとかによるので一概には言えなそう。オープンクラスで追加メソッドを生やすと全体に影響が出てしまいコードと実行結果の対応づけは動的にしか解決できないらしい。拡張関数の場合はクラススコープのみなので混乱は少ないというか静的に動作を解決できる。ダメな設計についてビルダーを可変のシングルトンにして排他制御している。リソースをコルーチン間で共有する必要はない。前にインスタンス化が必要になる。オブジェクト内に配置するのか?などの点で悩みは残る。