用于返回对象的对象或函数的Scala类型

时间:2012-02-22 08:16:20

标签: scala functional-programming

所以我进入Scala并且我有一个问题,如果我想做什么是可能的,或者是否有更好的方法。

我希望能够将一个Map作为参数,其键是字符串,或者0-args函数返回一个字符串。例如,

def main(args: List[String]){
    f = F(
      Map(
      "key" -> "value",
      "key2" ->(()=> {"valule2"})
    )
    )

    println(f("key"))

}
    case class F(arg: Map[String, ???]){
        def apply(s: String): String = {arg(s)}
    }

这显然无法编译。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:8)

在这种情况下,您可以使用scala.Either

scala> val map: Map[String, Either[String, () => String]] = Map.empty
map: Map[String,Either[String,() => String]] = Map()

scala> map + ("key" -> Left("value"))
res0: scala.collection.immutable.Map[String,Either[String,() => String]] = Map(key -> Left(value))

scala> res0("key")
res1: Either[String,() => String] = Left(value)

scala> map + ("key2" -> Right(() => "value2"))
res2: scala.collection.immutable.Map[String,Either[String,() => String]] = Map(key2 -> Right(<function0>))

scala> res2("key2")
res3: Either[String,() => String] = Right(<function0>)

更新

您可以使用类似的东西隐藏调用者的实现。

def toEither[T <: Any : Manifest](x: T): Either[String, () => String] =
  x match {
    case x: String => Left(x)
    case x: Function0[String] if manifest[T] <:< manifest[() => String] => Right(x)
    case _ => throw new IllegalArgumentException
  }

Function0的实际类型因类型删除而被删除,但可以使用Manifest

进行验证
scala> map + ("key" -> toEither("value"))
res1: scala.collection.immutable.Map[String,Either[String,() => String]] = Map(key -> Left(value))

scala> map + ("key2" -> toEither(() => "value2"))
res2: scala.collection.immutable.Map[String,Either[String,() => String]] = Map(key2 -> Right(<function0>))

scala> res2("key2").right.get()
res3: String = value2

scala> map + ("key2" -> toEither(() => 5))
java.lang.IllegalArgumentException

scala> map + ("key2" -> toEither(false))
java.lang.IllegalArgumentException

UPDATE2

由于@Submonoid在下面的评论中正确地纠正了我,因此有更简单的方法来处理Either

type StringOrFun = Either[String, () => String]
implicit def either(x: String): StringOrFun = Left(x)
implicit def either(x: () => String): StringOrFun = Right(x)

val m: Map[String, StringOrFun] = Map("key" -> "value", "key2" -> (() => "value2"))

答案 1 :(得分:3)

或者,您可以将任何字符串包装在一个计算结果为该字符串的函数中:

implicit def delayed[A](a : A) = () => a
val m = Map[String, () => String]("a" -> "b", "c" -> (() => "d"))