chisel可选值/模式匹配实例

一、scala可选值语法

可选值就是类型为Option[T]的一个值。其中,Option是标准库里的一个密封抽象类。T可以是任意的类型,例如标准类型或自定义的类。并且T是协变的,简单来说,就是如果类型T是类型U的超类,那么Option[T]也是Option[U]的超类。

Option类有一个子类:Some类。通过“Some(x)”可以构造一个Some的对象,其中参数x是一个具体的值。根据x的类型,可选值的类型会发生改变。例如,Some(10)的类型是Option[Int],Some(“10”)的类型是Option[String]。由于Some对象需要一个具体的参数值,所以这部分可选值用于表示“有值”。

Option类还有一个子对象:None。它的类型是Option[Nothing],是所有Option[T]类型的子类,代表“无值”。也就是说,Option类型代表要么是一个具体的值,要么无值。Some(x)常作为case语句的返回值,而None常作为通配模式的返回值。需要注意的是,Option[T]和T是两个完全没有关系的类型,赋值时不要混淆。

如果没有可选值语法,要表示“无值”可能会选用null,这就必须对变量进行判空操作。在Java里,判空是一个运行时的动作,如果忘记判空,编译时并不会报错,但是在运行时可能会抛出空指针异常,进而引发严重的错误。有了可选值之后,首先从字面上提醒读者这是一个可选值,存在无值和有值两种情况;其次,最重要的是,由于Option[T]类型与T类型不一样,赋值时就可能需要先做相应的类型转换。类型转换最常见的方式就是模式匹配,在这期间可以把无值None过滤掉。如果不进行类型转换,编译器就会抛出类型错误,这样在编译期就进行判空处理进而防止运行时出现更严重的问题。

可选值提供了一个方法isDefined,如果调用对象是None,则返回false,而Some对象都会返回true。还有一个方法get,用于把Some(x)中的x返回,如果调用对象是None则报错。

  • 当我们访问一个map缺少的键/值对时,就会出现一个运行时错误:
val map = Map("a" -> 1)
val a = map("a")
println(a)
val b = map("b")
println(b)

1
java.util.NoSuchElementException: key not found: b
scala.collection.immutable.Map M a p 1. a p p l y ( M a p . s c a l a : 114 ) a m m o n i t e . Map1.apply(Map.scala:114) ammonite. Map1.apply(Map.scala:114)ammonite.sess.cmd2 H e l p e r . < i n i t > ( c m d 2. s c : 4 ) a m m o n i t e . Helper.(cmd2.sc:4) ammonite. Helper.<init>(cmd2.sc:4)ammonite.sess.cmd2 . < i n i t > ( c m d 2. s c : 7 ) a m m o n i t e . .(cmd2.sc:7) ammonite. .<init>(cmd2.sc:7)ammonite.sess.cmd2$.(cmd2.sc:-1)

  • 但是,Map通过get方法提供了另一种访问键/值的方法。使用它将返回一个抽象类Option类型的值。Option有两个子类,Some 和 None
val map = Map("a" -> 1)
val a = map.get("a")
println(a)
val b = map.get("b")
println(b)

Some(1)
None
map: Map[String, Int] = Map(“a” -> 1)
a: Option[Int] = Some(1)
b: Option[Int] = None

  • Option类也提供了get方法,用来获取Some包含的具体数值,但是不能用None去调用,否则会报错;对于这种情况,我们可以使用getOrElse方法,当 None调用该方法时,可以返回指定的默认值。
val some = Some(1)
val none = None
println(some.get)          // Returns 1
// println(none.get)       // Errors!
println(some.getOrElse(2)) // Returns 1
println(none.getOrElse(2)) // Returns 2

1
1
2
some: Some[Int] = Some(1)
none: None.type = None

个人觉得可选值的主要作用是:当你不确定某个数据或者函数的返回值到底有没有值时,你可以将该数据的类型定义成Option[T]类型,这样无论它是有值(如Option[Int])还是没有值(Option[Nothing])都属于同一个类型,这样就不会出错。

二、chisel可选值使用实例

当对象或函数有很多参数时,总是完全地指定它们可能是乏味和容易出错的。使用默认值的话有时参数并没有很好的默认值,那么这种情况下就可以使用Option[T]类型的默认值None

下面的例子是将输入延迟一个时钟周期的模块。如果resetValue=None(这是默认值),则寄存器将没有重置值,并被初始化为 garbage。这可以避免使用正常范围以外的值来表示none,例如使用-1作为重置值来指示此寄存器未被重置。

class DelayBy1(resetValue: Option[UInt] = None) extends Module {
    val io = IO(new Bundle {
        val in  = Input( UInt(16.W))
        val out = Output(UInt(16.W))
    })
    val reg = if (resetValue.isDefined) { // resetValue = Some(number)
        RegInit(resetValue.get)
    } else { //resetValue = None
        Reg(UInt())
    }
    reg := io.in
    io.out := reg
}

三、chisel模式匹配使用实例

上述例子,也可以改成使用模式匹配来实现,如下所示:

class DelayBy1(resetValue: Option[UInt] = None) extends Module {
  val io = IO(new Bundle {
    val in  = Input( UInt(16.W))
    val out = Output(UInt(16.W))
  })
  val reg = resetValue match {
    case Some(r) => RegInit(r)
    case None    => Reg(UInt())
  }
  reg := io.in
  io.out := reg
}

你可能感兴趣的:(#,chisel学习笔记,scala,chisel,可选值,模式匹配)