元组被视为Product,编译器拒绝对元素的引用

时间:2015-04-01 22:47:55

标签: scala

构建phoneVector:

  val phoneVector = (
    for (i <- 1 until 20) yield {
      val p = killNS(r.get("Phone %d - Value" format(i)))
      val t = killNS(r.get("Phone %d - Type" format(i)))
        if (p == None) None
        else
          if (t == None) (p,"Main") else (p,t)
    }
  ).filter(_ != None)

考虑这个非常简单的片段:

  for (pTuple <- phoneVector) {
    println(pTuple.getClass.getName)
    println(pTuple)
    //val pKey = pTuple._1.replaceAll("[^\\d]","")
    associate() // stub prints "associate"
  }

当我运行它时,我看到这样的输出:

scala.Tuple2
((609) 954-3815,Mobile)
associate

当我用replaceAll()取消注释该行时,编译失败:

....scala:57: value _1 is not a member of Product with Serializable
[error]         val pKey = pTuple._1.replaceAll("[^\\d]","")
[error]                           ^

为什么它不会将pTuple识别为Tuple2并仅将其视为Product

3 个答案:

答案 0 :(得分:0)

好的,这会编译并产生所需的结果。但它太冗长了。有人可以为处理这种类型安全的东西展示一个更简洁的解决方案吗?

  for (pTuple <- phoneVector) {
    println(pTuple.getClass.getName)
    println(pTuple)
    val pPhone = pTuple match {
      case t:Tuple2[_,_] => t._1
      case _ => None
    }
    val pKey = pPhone match {
      case s:String => s.replaceAll("[^\\d]","")
      case _ => None
    }
    println(pKey)
    associate()
  }

答案 1 :(得分:0)

你可以这样做:

  for (pTuple <- phoneVector) {
    val pPhone = pTuple match {
      case (key, value) => key
      case _ => None
    }
    val pKey = pPhone match {
      case s:String => s.replaceAll("[^\\d]","")
      case _ => None
    }
    println(pKey)
    associate()
  }

或只是phoneVector.map(_._1.replaceAll("[^\\d]",""))

答案 2 :(得分:0)

通过改变phoneVector的结构,正如wrick的问题暗示的那样,我已经能够消除匹配/案例的东西,因为元组是有保证的。没有激动,但改变很难,Scala看起来很酷。

现在,仍然可以将None值滑入任何一个Tuple值。我的匹配/案例没有检查,我怀疑这可能导致replaceAll调用中的运行时错误。这是怎么允许的?

  def killNS (s:Option[_]) = {
    (s match {
      case _:Some[_] => s.get
      case _ => None
    }) match {
      case None => None
      case "" => None
      case s => s
    }
  }

  val phoneVector = (
    for (i <- 1 until 20) yield {
      val p = killNS(r.get("Phone %d - Value" format(i)))
      val t = killNS(r.get("Phone %d - Type" format(i)))
      if (t == None) (p,"Main") else (p,t)
    }
  ).filter(_._1 != None)
  println(phoneVector)
  println(name)
  println
  // Create the Neo4j nodes:
  for (pTuple <- phoneVector) {
    val pPhone = pTuple._1 match { case p:String => p }
    val pType = pTuple._2
    val pKey = pPhone.replaceAll(",.*","").replaceAll("[^\\d]","")
    associate(Map("target"->Map("label"->"Phone","key"->pKey,
                                                 "dial"->pPhone),
                  "relation"->Map("label"->"IS_AT","key"->pType),
                  "source"->Map("label"->"Person","name"->name)
                 )
             )
  }
}