map
型に対して暗黙の引数で定義されたいくつかのメソッドを試してみると問題が発生しOption
ます。
私がカスタムを定義class
しtrait
、前述のメソッドが上記で動作しているとしましょうclass
class MyClass
trait Processor {
def stringy(implicit arg: MyClass) = arg.toString
def lengthy(implicit arg: MyClass) = arg.toString.length
def inty(implicit arg: MyClass) = arg.toString.map(_.toInt).sum
}
次に、いくつかのテストを使用して実装を作成します
object TestProcessing extends Processor {
//Here everything works fine, the argument is passed explicitly
def test() {
val my = new MyClass
val res = List(stringy(my), lengthy(my), inty(my))
println(res.mkString("\n"))
}
//Still everything ok, the argument is passed implicitly
def testImplicit() {
implicit val my = new MyClass
val res = List(stringy, lengthy, inty)
println(res.mkString("\n"))
}
object Mapper {
//class wrapped in an Option
val optional = Some(new MyClass)
//trying to factor out common code
def optionally[T](processFunction: MyClass => T): Option[T] = optional map processFunction
//now the specific processing methods that should work on the optional value
def s: Option[String] = optionally(stringy)
def l: Option[Int] = optionally(lengthy)
def i: Option[Int] = optionally(inty)
/*
* Here the compiler complains that
*
*<console>:40: error: could not find implicit value for parameter arg: MyClass
* def s: Option[String] = optionally(stringy)
* ^
*<console>:41: error: could not find implicit value for parameter arg: MyClass
* def l: Option[Int] = optionally(lengthy)
* ^
*<console>:42: error: could not find implicit value for parameter arg: MyClass
* def i: Option[Int] = optionally(inty)
* ^
*/
}
}
オプションの値をoptionally
引数関数に明示的に渡すと考えられていますが、実際の関数で使用する場合、コンパイラーは暗黙の定義を要求します。
私には2つの可能な解決策がありますが、どちらも満足のいくものではありません。
のように暗黙の引数を
optionally
渡すoptionally(implicit my => stringy)
のように、特定の関数への引数をとして定義することは避けて
implicit
くださいdef stringy(arg: MyClass)
各ソリューションは、読みやすさと使いやすさの両方を達成するという目標に反しています。
行くための3番目の方法はありますか?