码迷,mamicode.com
首页 > 其他好文 > 详细

快学scala 第十一章 操作符 读书笔记及习题答案代码

时间:2016-07-22 19:24:58      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

chapter 11 操作符

标签:快学scala


一、笔记

  1. scala种可以在反引号中包含几乎任何字符序列,
  1. val ‘val‘ = 42

所有的操作符都是左结合的,除了以冒号(:)结尾的操作符,和赋值操作符。用于构造列表的::操作符是又结合的。1::2::Ni1的意思是1::(2::Ni1),先创建出包含2的列表,这个列表又被作为尾巴拼接到以1作为头部的列表中。 
2. 函数调用语法:f(arg1, arg2,...)扩展到可以应用于函数之外的值,如果f不是函数或方法,那么这个表达式等于f.apply(arg1,arg2,....)。除非它出现在赋值语句的等号左侧。

  1. f(arg1,arg2,...) = value 等同于如下调用
  2. f.update(arg1,arg2,....,value)
  1. 提取器是一个unapply方法的对象,可以把unapply方法当做是伴生对象中apply方法的方向操作。apply接受构造参数,然后将它们变成对象,unapply方法接受一个对象,然后从中提取值,通常这些值就是当初用来构造该对象的值。 
    unapply方法返回的是一个Option,它包含一个元组,每个匹配到的变量各有一个值与之对应。
  1. object Fraction{
  2. def unapply(input: Fraction)=
  3. if(input.den == 0) None else Some((input.num, input.den))
  4. } //方法在分母为0时返回None,表示无匹配。
  1. 要提取任意长度的值的序列,我们应该用unapplySeq来命名我们的方法,它返回一个Option[Seq[A]],其中A是被提取的值的类型。比如,Name提取器可以产出名字中所有组成部分的序列:
  1. object Name{
  2. def unapplySeq(input: String): Option[Seq[A]] =
  3. if(input.trim == "") None else Some(input.trim.split("\\s+"))
  4. }
  5. //匹配任意数量的变量
  6. author match{
  7. case Name(first, last) =>..
  8. case Name(first, middle,last)=>..
  9. ...
  10. }

二、习题答案

11.1 根据优先级规则,3 + 4 -> 5和3 -> 4 + 5是如何被求值的?

都是从左至右执行,所以 3 -> 4 + 5表达式是不合法的。

11.2 BigInt类有一个pow方法,但没有用操作符字符。Scala类库的设计者为什么没有选用**(像Fortran那样)或者^(像Pascal那样)作为乘方操作符呢?

scala中操作符就是方法,优先级是根据首字母来判断的。
  1. 最高优先级:除以下字符外的操作符字符
  2. * / %
  3. + -
  4. :
  5. = !
  6. < >
  7. &
  8. ?
  9. |
  10. 非操作符
  11. 最低优先级:赋值操作符
一般乘方操作符优先于乘法操作,如果使用**作为乘方的话,那么其优先级则与*相同,而如果使用^的话,则优先级低于*操作。优先级都是有问题的。故没有使用这两种操作符。

11.3 实现Fraction类,支持+*/操作。支持约分,例如将15/-6变为-5/2。除以最大公约数,像这样:

  1. class Fraction(n:Int,d:Int){
  2. private val num:Int = if(d==0) 1 else n * sign(d)/gcd(n,d);
  3. private val den:Int = if(d==0) 0 else d * sign(d)/gcd(n,d);
  4. override def toString = num + "/" + den
  5. def sign(a:Int) = if(a > 0) 1 else if (a < 0) -1 else 0
  6. def gcd(a:Int,b:Int):Int = if(b==0) abs(a) else gcd(b,a%b)
  7. ...
  8. }
  1. import scala.math.abs
  2. class Fraction(n: Int, d: Int){
  3. private val num: Int = if(d == 0)1 else n *sign(d)/gcd(n,d)
  4. private val den: Int = if(d == 0)0 else d * sign(d)/gcd(n,d)
  5. override def toString = num + "/" +den
  6. def sign(a: Int) = if(a >0)1 else if(a <0) -1 else 0
  7. def gcd(a: Int, b: Int): Int = if(b == 0) abs(a) else gcd(b, a%b)
  8. def +(other: Fraction): Fraction= {
  9. new Fraction((this.num * other.den) + (other.num *this.den), this.den * other.den)
  10. }
  11. def -(other: Fraction): Fraction={
  12. new Fraction((this.num * other.den) - (other.num *this.den), this.den * other.den)
  13. }
  14. def *(other: Fraction): Fraction={
  15. new Fraction(this.num * other.num, this.den * other.den)
  16. }
  17. def / (other: Fraction): Fraction={
  18. new Fraction(this.num * other.den, this.den * other.num)
  19. }
  20. }
  21. object Fraction{
  22. def apply(n: Int, d: Int) = new Fraction(n, d)
  23. }
  24. val x = Fraction(15, -6)
  25. val y = Fraction(20,60)
  26. println(x)
  27. println( x + y)
  28. println( x * y)

11.4 实现一个Money类,加入美元和美分字段。提供+,-操作符以及比较操作符==和<。举例来说,Money(1,75)+Money(0,50)==Money(2,25)应为true。你应该同时提供*和/操作符吗?为什么?

  1. class Money(d: BigInt, c: BigInt) extends Ordered[Money]{
  2. val dollars: BigInt = d + c /100
  3. val cents: BigInt = c % 100
  4. override def toString() = "%d.%d".format(dollars, cents)
  5. def toCents(): BigInt = dollars * 100 + cents
  6. def fromCents(cents: BigInt) = new Money(cents / 100, cents % 100)
  7. override def compare(that: Money): Int = toCents.compare(that.toCents)
  8. def + (that: Money) = fromCents(this.toCents + that.toCents)
  9. def - (that: Money) = fromCents(this.toCents - that.toCents)
  10. }
  11. object Money{
  12. def apply(d: Int, c: Int) = new Money(d, c)
  13. }
  14. val x = Money(1, 75)
  15. val y = Money(0, 50)
  16. println(x + y)
  17. println(x - y)
  18. println(x > y) //true

11.5 提供操作符用于构造HTML表格。例如:Table() | "Java" | "Scala" || "Gosling" | "Odersky" || "JVM" | "JVM,.NET"应产出

  1. :<table><tr><td>Java</td></tr><td>Scala</td></tr><tr><td>Gosling
  1. import collection.mutable.ArrayBuffer
  2. class Table{
  3. private val chunks = new ArrayBuffer[String]
  4. def | (chunk: String)= {
  5. chunks += "<td>%s</td>\n".format(chunk)
  6. this
  7. }
  8. def ||(chunk: String) = {
  9. chunks += "</tr><tr>\n<td>%s</td>".format(chunk)
  10. this
  11. }
  12. override def toString = "<table><tr>\n%s</tr><table".format(chunks.mkString)
  13. }
  14. object Table{
  15. def apply() = new Table()
  16. }
  17. val t = Table() | "Java" | "Scala" || "Gosling" | "Odersky" || "JVM" | "JVM,.NET"
  18. println(t)

11.6 提供一个ASCIIArt类,其对象包含类似这样的图形:

  1. /\_/\
  2. ( ‘ ‘ )
  3. ( - )
  4. | | |
  5. (__|__)
  6. 提供将两个ASCIIArt图形横向或纵向结合的操作符。选用适当优先级的操作符命名。纵向结合的实例
  7. /\_/\ -----
  8. ( ‘ ‘ ) / Hello \
  9. ( - ) < Scala |
  10. | | | \ Coder /
  11. (__|__) -----
  1. class ASCIIArt(val art: String){
  2. def +(other: ASCIIArt) = new ASCIIArt(
  3. art.split("\n").zip(other.art.split("\n")).map(x => x._1 + x._2).mkString("\n")
  4. )
  5. def ^(other: ASCIIArt) = new ASCIIArt( art + "\n" + other.art)
  6. override def toString = art
  7. }
  8. val x = new ASCIIArt(
  9. """ /\_/\
  10. ( ‘ ‘ )
  11. ( - )
  12. | | |
  13. (__|__)""")
  14. val y = new ASCIIArt(
  15. """ -----
  16. / Hello \
  17. < Scala |
  18. \ Coder /
  19. -----""")
  20. println(x + y)
  21. println(x ^ y)

11.7 实现一个BigSequence类,将64个bit的序列打包在一个Long值中。提供apply和update操作来获取和设置某个具体的bit

  1. class BitSequence(private var value: Long = 0){
  2. implicit def bool2int(b: Boolean) = if(b) 1 else 0
  3. def update(bit: Int, state: Int) = value |= (state & 1L)<< bit % 64
  4. def apply(bit: Int): Int = if((value & 1L << bit % 64) > 0) 1 else 0
  5. override def toString = "%64s".format(value.toBinaryString).replace(" ", "0")
  6. }
  7. val x = new BitSequence()
  8. x(5) = 1
  9. x(63) = 1
  10. x(64) = 1
  11. println(x(5))
  12. println(x)

11.8 提供一个Matrix类—你可以选择需要的是一个2*2的矩阵,任意大小的正方形矩阵,或m*n的矩阵。支持+和操作。操作应同样适用于单值,例如mat*2。单个元素可以通过mat(row,col)得到

  1. class Matrix(val m: Int, val n: Int){
  2. private val value = Array.ofDim[Double](m, n)
  3. def update(x: Int, y: Int, v: Double) = value(x)(y) = v
  4. def apply(x: Int, y: Int) = value(x)(y)
  5. def +(other: Matrix) = {
  6. require (n == other.n)
  7. require (m == other.m)
  8. var res = new Matrix(m,n)
  9. for(i <- 0 until m; j <- 0 until n){
  10. res(i, j) = this.value(i)(j) + other.value(i)(j)
  11. }
  12. res
  13. }
  14. def *(factor: Double) = {
  15. var res = new Matrix(m, n)
  16. for(i <- 0 until m; j <- 0 until n) {
  17. res(i, j) = this.value(i)(j) * factor
  18. }
  19. res
  20. }
  21. private def prod(other: Matrix, i: Int, j: Int) = {
  22. (for (k <- 0 until n) yield value(i)(k) * other.value(j)(k)).sum
  23. }
  24. def *(other: Matrix) = {
  25. require(n == other.m)
  26. var res = new Matrix(m, n)
  27. for(i <- 0 until m; j <- 0 until n) {
  28. res(i, j) = prod(other, i, j)
  29. }
  30. res
  31. }
  32. override def toString = value.map(_.mkString(" ")).mkString("\n")
  33. }
  34. val x = new Matrix(2,3)
  35. x(0, 0) = 1
  36. x(0, 0) = 1
  37. x(1, 0) = 3
  38. x(1, 1) = 4
  39. println(x)
  40. println()
  41. println(x * 2)
  42. println()

11.9 为RichFile类定义unapply操作,提取文件路径,名称和扩展名。举例来说,文件/home/cay/readme.txt的路径为/home/cay,名称为readme,扩展名为txt

  1. object RichFile{
  2. def unapply(s: String) = {
  3. val pos = s.lastIndexOf("/")
  4. if(pos == -1) None else Some((s.substring(0, pos), s.substring(pos+1)))
  5. }
  6. }
  7. val RichFile(path, name) = "/home/user/scala/test.txt"
  8. println("Path: %s, File: %s".format(path, name))

11.10 为RichFile类定义一个unapplySeq,提取所有路径段。举例来说,对于/home/cay/readme.txt,你应该产出三个路径段的序列:home,cay和readme.txt

  1. object RichFile {
  2. def unapplySeq(s: String): Option[Seq[String]] = {
  3. if (s.trim == "") None else Some(s.trim.split("/"))
  4. }
  5. }
  6. val RichFile(first, middle, last) = "home/user/text.txt"
  7. println("First: %s, Middle: %s, Last: %s".format(first, middle, last))

快学scala 第十一章 操作符 读书笔记及习题答案代码

标签:

原文地址:http://blog.csdn.net/refuil/article/details/51991601

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!