Scalaでperlのorみたいなやつ
ScalaでPerlのorみたいに、val a:String = foo or "bar" のように、fooがnullとか""だったら"bar"が設定されるようにしたい。
使いどころはあまりないと思うけど、練習がてら作ってみたらエライ大変だった。
はまったのは、implicit parameterを適用する際の型パラメータの共変、反変のところ。
チェック対象の変数の型によって、どんな状態だと"空"だと判断するのを、PartialFunctionとしてimplicit parameterで定義しようとしてやられました。
あとで詳しい解説書きます。
object OrOp{
class OrOp[T]( v:T) {
def or( f:() => T )( implicit orPf:OrPF[T,T] ) = {
if( orPf.pf.isDefinedAt( v ) ) f()
else v
}
def or( other:T )( implicit orPf:OrPF[T,T] ) = {
if( orPf.pf.isDefinedAt( v ) ) other
else v
}
}
implicit def any2OrOp[T]( v:T ) = new OrOp(v)
class OrPF[-T,+U]( val pf:PartialFunction[T,U] )
implicit val anyrefPF:OrPF[AnyRef,AnyRef] = new OrPF[AnyRef,AnyRef]({
case null => null
})
implicit val stringPF:OrPF[String,String] = new OrPF[String,String]({
case null => null
case xs:String if xs.size == 0 => xs
})
val opf:PartialFunction[Option[Any],Option[Nothing]] = {
case null => null
case None => None
}
implicit val optionPF:OrPF[Option[Any],Option[Nothing]] = new OrPF[Option[Any],Option[Nothing]]( opf )
val lpf:PartialFunction[List[Any],List[Nothing] ]= {
case null => null
case Nil => Nil
}
implicit val listPF:OrPF[List[Any],List[Nothing]] = new OrPF[List[Any],List[Nothing]]( lpf )
val cpf:PartialFunction[Collection[Any] ,Collection[Nothing] ] = {
case null => null
case xs if xs.size == 0 => null
}
implicit val collectionPF: OrPF[Collection[Any],Collection[Nothing]] = new OrPF[Collection[Any],Collection[Nothing]]( cpf )
}
実行すると
scala> import OrOp._
import OrOp._
scala> val l:List[Int] = Nil
l: List[Int] = List()
scala> l or List(1,2,3)
res24: List[Int] = List(1, 2, 3)
scala> val c:Collection[String] = Set()
c: Collection[String] = Set()
scala> c or Set("foo","bar")
res25: Collection[String] = Set(foo, bar)
scala> val o:Option[List[Int]] = None
o: Option[List[Int]] = None
scala> o or Some(List(1,2))
res26: Option[List[Int]] = Some(List(1, 2))