Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用scala提取器将字符串强制转换为Int_Scala_Type Conversion_Implicit Conversion_Unapply - Fatal编程技术网

使用scala提取器将字符串强制转换为Int

使用scala提取器将字符串强制转换为Int,scala,type-conversion,implicit-conversion,unapply,Scala,Type Conversion,Implicit Conversion,Unapply,我正在尝试使用提取器将字符串转换为Int。我的代码如下所示 object Apply { def unapply(s: String): Option[Int] = try { Some(s.toInt) } catch { case _: java.lang.Exception => None } } object App { def toT[T](s: AnyRef): Option[T] = s match { case v: T =>

我正在尝试使用提取器将
字符串
转换为
Int
。我的代码如下所示

object Apply {
  def unapply(s: String): Option[Int] = try {
    Some(s.toInt)
  } catch {
    case _: java.lang.Exception => None
  }
}

object App {
  def toT[T](s: AnyRef): Option[T] = s match {
    case v: T => Some(v)
    case _ => None
  }
  def foo(param: String): Int = {
    //reads a Map[String,String] m at runtime
    toT[Int](m("offset")).getOrElse(0)
  }
}
我得到一个运行时错误:
java.lang.String无法转换为java.lang.Integer
。似乎根本就没有人使用这个提取器。我该怎么办

编辑:我的用例如下。我正在使用play,我想解析url中传递的查询字符串。我想使用查询字符串值(string)并将其用作Int、Double等。例如

val offset = getQueryStringAs[Int]("offset").getOrElse(0)

代码中存在问题,您应该收到编译器警告:

def toT[T](s: AnyRef): Option[T] = s match {
  case v: T => Some(v) // this doesn't work, because T is erased
  case _ => None
}
现在。。。应在哪里应用
?我看到它被宣布,但我没有看到它在任何地方使用

编辑

关于警告,请查看有关堆栈溢出上类型擦除的讨论。例如,我写了一篇关于如何绕过它的文章——尽管现在Scala 2.10.0不推荐使用它

为了解决您的问题,我会使用类型类。例如:

abstract class Converter[T] {
  def convert(s: String): T
}

object Converter {
  def toConverter[T](converter: String => T): Converter[T] = new Converter[T] {
    override def convert(s: String): T = converter(s)
  }

  implicit val intConverter = toConverter(_.toInt)
  implicit val doubleConverter = toConverter(_.toDouble)
}
然后您可以像这样重写您的方法:

val map = Map("offset" -> "10", "price" -> "9.99")

def getQueryStringAs[T : Converter](key: String): Option[T] = {
  val converter = implicitly[Converter[T]]
  try {
    Some(converter convert map(key))
  } catch {
    case ex: Exception => None
  }
}
使用中:

scala> getQueryStringAs[Int]("offset")
res1: Option[Int] = Some(10)

scala> getQueryStringAs[Double]("price")
res2: Option[Double] = Some(9.99)

我认为这里最大的问题是,你似乎混淆了铸造和转换。您有一个
映射[String,String]
,因此无法将值强制转换为
Int
。你必须转换它们。幸运的是,Scala通过对StringOps的隐式转换将
toInt
方法添加到字符串中

这应该适合您:

m("offset").toInt
请注意,如果字符串不能转换为整数,
toInt
将抛出
java.lang.NumberFormatException

编辑

您想要的仅适用于类型类

以下是一个例子:

trait StringConverter[A] {
  def convert(x: String): A
}

implicit object StringToInt extends StringConverter[Int] {
  def convert(x: String): Int = x.toInt
}

implicit object StringToDouble extends StringConverter[Double] {
  def convert(x: String): Double = x.toDouble
}

implicit def string2StringConversion(x: String) = new {
  def toT[A](implicit ev: StringConverter[A]) = ev.convert(x)
}
用法:

scala> "0.".toT[Double]
res6: Double = 0.0

为什么您希望使用它?您将问题标记为“隐式转换”,您的代码中没有隐式转换。
toT[T]。。。案例五:T
不起作用,T在擦除中丢失。从根本上讲,不可能将
字符串转换为任何其他类型(除了
AnyRef
any
)。如果使用play 2.1.0(使用scala 2.10),则可以在
String
上定义“扩展”方法:
隐式类StringConversionOps(val str:String)扩展AnyVal{def parseInt=try{Some(str.toInt)}catch{case{uu=>None}}
。您可以根据需要向该类添加方法。然后假设它在范围内,您可以执行
m(“offset”).parseInt.getOrElse(0)
。我确实收到了该警告,但还是忽略了它。那么,我应该怎么做呢?理想情况下,我应该能够调用toT[Int],toT[Double]等,它们应该使用适当的unapply。这很好,但我想要的是一个通用的toT[T]方法。好的,谢谢,这是唯一的方法吗?为什么类型匹配不起作用?因为1)您的值是string类型,2)
T
将被擦除,并且在运行时不可用(这实际上可以通过使用
Manifest
/
TypeTag
来解决,但仍然有字符串需要转换)。好的,我将使用typeclasses,然后为convert使用选项[A]返回类型,因为没有
StringConverter[T]
的实例。请尝试
def foo[A:StringConverter]
,这称为类型绑定,并将类型为
StringConverter[a]
的隐式参数添加到方法中,然后用于调用
toT[a]