加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala Cons模式匹配如何确定List的头部和尾部?

发布时间:2020-12-16 18:33:46 所属栏目:安全 来源:网络整理
导读:如何在以下声明中确定头部和尾部: val head::tail = List(1,2,3,4); //head: 1 tail: List(2,4) 不应该有一些代码将第一个元素提取为head并将尾部作为新List返回.我一直在梳理Scala标准库代码,但我找不到/理解这是怎么做的. 解决方法 这里涉及的Scala构造是
如何在以下声明中确定头部和尾部:

val head::tail = List(1,2,3,4);
 //head: 1  tail: List(2,4)

不应该有一些代码将第一个元素提取为head并将尾部作为新List返回.我一直在梳理Scala标准库代码,但我找不到/理解这是怎么做的.

解决方法

这里涉及的Scala构造是 Extractor.符号 ::只不过是Scala中的一个case类,其伴随对象上存在一个unapply方法,以使提取魔法发生. Here是关于提取器的一个很好的深入教程.但这是摘要:

每当您想要“解包”类的内容时,无论是对于变量绑定还是作为模式匹配的一部分,编译器都会在表达式左侧的任何符号上查找该方法的unapply.这可能是一个对象,一个案例类伴随对象(如你的问题中的::,)或一个带有unapply的实例. unapply的参数是要解包的传入类型,返回类型是已声明为预期结构和类型的选项.在模式匹配中,无表示未找到匹配项.在变量绑定中,如果结果为None,则抛出MatchError.

思考不适用的好方法是它与应用相反.在不应用函数调用语法的接收器的情况下,unapply是提取器调用的接收器.

为了进一步说明这一点,让我们定义一个简单的案例类:

case class Cat(name: String,age: Int)

因为它是一个案例类,我们会在随播对象上自动生成apply和unapply方法,大致如下所示:

object Cat {
  // compiler generated...
  def apply(name: String,age: Int) = new Cat(name,age)    
  def unapply(aCat: Cat): Option[(String,Int)] = Some((aCat.name,aCat.age))
}

通过配套对象创建Cat时,将调用apply.当您解开Cat的组成部分时,将调用unapply:

val mycat = Cat("freddy",3) // `apply` called here
...
val Cat(name,age) = mycat   // `unapply` called here
...
val animal: AnyRef = mycat
val info = animal match {
  case Cat(name,age) => "My pet " + name // `unapply` called here
  case _ => "Not my pet"
}
// info: String = My pet freddy

因为unapply返回一个Option,所以我们有很多权力来编写处理更有趣案例的提取器,例如,在提取值之前测试传入类型是否符合某些条件.例如,假设我们想获得“旧”的猫的名字.有人可能这样做:

object OldCatName {
  def unapply(aCat: Cat) = if (aCat.age >= 10) Some(aCat.name) else None
}

用法与生成的unapply相同:

val yourcat = Cat("betty",12)
...
val OldCatName(name1) = yourcat
// name1: String = "betty"
val OldCatName(name2) = mycat
// scala.MatchError: Cat(freddy,3) (of class Cat)

MatchErrors不是一件好事,所以让我们使用模式匹配:

val conditions = Seq(mycat,yourcat) map { 
  case OldCatName(oldie) => s"$oldie is old"
  case Cat(name,age) => s"At age $age $name is not old"
}
// conditions: Seq[String] = List(At age 3 freddy is not old,betty is old)

与::的unapply方法有关的一个额外的魔法就是一些语法糖允许val ::

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读