なにやってるんだ・・・、と思いつつ見てたら、とりあえず解答を思いついてしまったので貼っておきます。
ちなみに、あくまで解答"例"であって、他にも色々方法あるかもしれません。
ちゃんと調べきれてないので確証が全く無いのですが、「Type Dynamicによるメソッド呼び出しのselectDynamicへの変換」と「implicit classによる暗黙の型変換」は両立しないみたい・・・?
はい、自分の知る限り両立しないです。なので、方針を説明すると
- 最初の一回だけ明示的にDynamic用のオブジェクトにラップする処理を書く
- _valueとかを呼び出したら、OptionではなくDynamic用のオブジェクトにラップしたまま返す
- あと、valueに限らないものができたので、 _valueでなくても _hoge でも、むしろアンダースコアなしでもいいようになった
- Dynamicなオブジェクトから最後にOptionに戻すのには、これも明示的に書いてもいいけど、この場合の逆の変換はimplicit conversionでもできるので定義しておく
- Option[A] と Option[ Option[A] ] でラップ用オブジェクトわけるの難しいというか、逆に面倒なので、ラップ用オブジェクトは1つにして、全部マクロで頑張る
というわけで、こうなりました
追加でScalaのマクロ的なことを含め、自分のコードを説明すると
- どうせwhitebox使ってるんだし、最初からselectDynamicの型はAnyにしてしまった(Anyのサブタイプ == 任意の型を返す、ということ)
- Optionがネストしてるのかしてないのかは、頑張ってマクロで判断してるわけだが、その部分かなり雑なので、もっと綺麗な書き方ありそう。バグも色々残ってそう
- 色々チェックをサボってるので、よくも悪くも、Option以外でも、mapやflattenを持ってると呼び出せてしまうはず?
ところでマクロの練習としては面白いけど、実用するにはどう考えてもマクロやDynamicの間違った使い方な感じしかしないので、やめたほうがいいですね・・・。