1 根据优先级规则,3 + 4 -> 5和3 -> 4 + 5是如何被求值的?
scala> 3+4 -> 5
res0: (Int, Int) = (7,5)
//构成了元组
scala> 3->4+5
<console>:12: error: type mismatch;
found : Int(5)
required: String
3->4+5
^
scala> 3->4+"5"
res4: String = (3,4)5
除赋值外,从左至右操作
2 BigInt类有一个pow方法,但没有用操作符字符。Scala类库的设计者为什么没有选用**(像Fortran那样)或者^(像Pascal那样)作为乘方操作符呢?
因为优先级问题,在scala中*优先于^,但数学中乘方优先于乘法。所以没有提供^作为乘方的操作符
3 实现Fraction类,支持+*/操作。支持约分,例如将15/-6变为-5/2。除以最大公约数,像这样:
class Fraction(n:Int,d:Int){
private val num:Int = if(d==0) 1 else n * sign(d)/gcd(n,d);
private val den:Int = if(d==0) 0 else d * sign(d)/gcd(n,d);
override def toString = num + "/" + den
def sign(a:Int) = if(a > 0) 1 else if (a < 0) -1 else 0
def gcd(a:Int,b:Int):Int = if(b==0) abs(a) else gcd(b,a%b)
...
}
import math.abs
class Fraction(n: Int, d: Int) {
val num: Int = if (d == 0) 1 else n * sign(d) / gcd(n, d)
val den: Int = if (d == 0) 0 else d * sign(d) / gcd(n, d)
override def toString = num + "/" + den
//改负数为分子
def sign(a: Int): Int = if (a > 0) 1 else if (a < 0) -1 else 0
//求最大公约数
def gcd(a: Int, b: Int): Int = if (b == 0) abs(a) else gcd(b, a % b)
//加法
def +(that: Fraction): Fraction = {
Fraction((this.num * that.den) + (this.num * that.den), this.den * that.num)
}
def -(that: Fraction): Fraction = {
Fraction((this.num * that.den) - (this.num * that.den), this.den * that.num)
}
}
object Fraction {
def apply(a: Int, b: Int) = { new Fraction(a, b) }
}
4 实现一个Money类,加入美元和美分字段。提供+,-操作符以及比较操作符==和<。举例来说,Money(1,75)+Money(0,50)==Money(2,25)应为true。你应该同时提供*和/操作符吗?为什么?
class Money(val m: Double) {
def +(that: Money): Money = { Money(this.m + that.m) }
def -(that: Money): Money = { Money(this.m - that.m) }
def ==(that: Money): Boolean = { if (this.m == that.m) true else false }
}
object Money {
def apply(m: Double): Money = { new Money(m) }
}
object XX extends App {
println(Money(3.5) + Money(3.7) == Money(2.0))
}
不应该,无法控制优先级
5 提供操作符用于构造HTML表格。例如:Table() | “Java” | “Scala” || “Gosling” | “Odersky” || “JVM” | “JVM,.NET”应产出
class Table {
var s: String = ""
def |(str: String): Table = {
Table(this.s + "<td>" + str + "</td>")
}
def ||(str: String): Table = {
Table(this.s + "</tr><tr><td>" + str + "</td>")
}
override def toString: String = {
"<table><tr>" + this.s + "</tr></table>"
}
}
object Table {
def apply(): Table = {
new Table
}
def apply(str: String): Table = {
val t = new Table
t.s = str
t
}
}
object Five extends App {
println(Table() | "Java" | "Scala" || "Gosling" | "Odersky" || "JVM" | "JVM,.NET")
}
6 提供一个ASCIIArt类,其对象包含类似这样的图形:
import scala.collection.mutable.ArrayBuffer
class ASCIIArt(str: String) {
val arr: ArrayBuffer[ArrayBuffer[String]] = new ArrayBuffer[ArrayBuffer[String]]()
if (str != null && !str.trim.equals("")) {
str.split("[\r\n]+").foreach(
line => {
val s = new ArrayBuffer[String]()
s += line
arr += s
}
)
}
def this() {
this("")
}
/**
* 横向结合
* @param other
* @return
*/
def +(other: ASCIIArt): ASCIIArt = {
val art = new ASCIIArt()
// 获取最大行数
val length = if (this.arr.length >= other.arr.length) this.arr.length else other.arr.length
for (i <- 0 until length) {
val s = new ArrayBuffer[String]()
// 获取this中的行数据, 行数不足,返回空行
val thisArr: ArrayBuffer[String] = if (i < this.arr.length) this.arr(i) else new ArrayBuffer[String]()
// 获取other中的行数据, 行数不足,返回空行
val otherArr: ArrayBuffer[String] = if (i < other.arr.length) other.arr(i) else new ArrayBuffer[String]()
// 连接this
thisArr.foreach(s += _)
// 连接other
otherArr.foreach(s += _)
art.arr += s
}
art
}
/**
* 纵向结合
* @param other
* @return
*/
def *(other: ASCIIArt): ASCIIArt = {
val art = new ASCIIArt()
this.arr.foreach(art.arr += _)
other.arr.foreach(art.arr += _)
art
}
override def toString = {
var ss: String = ""
arr.foreach(ss += _.mkString(" ") + "\n")
ss
}
}
object Six extends App {
// stripMargin: "|"符号后面保持原样
val a = new ASCIIArt(
""" /\_/\
|( ' ' )
|( - )
| | | |
|(__|__)
| """.stripMargin)
val b = new ASCIIArt(
""" -----
| / Hello \
|< Scala |
| \ Coder /
| -----
| """.stripMargin)
println(a + b * b)
println((a + b) * b)
println(a * b)
}
7 实现一个BigSequence类,将64个bit的序列打包在一个Long值中。提供apply和update操作来获取和设置某个具体的bit
class BigSequence(private var value: Long = 0) {
def update(bit: Int, state: Int) = {
if (state == 1) value |= (state & 1L) << bit % 64
else value &= ~(1L << bit % 64)
}
def apply(bit: Int): Int = if (((value >> bit % 64) & 1L) > 0) 1 else 0
override def toString = "%64s".format(value.toBinaryString).replace(" ", "0")
}
object Seven {
def main(args: Array[String]) {
val x = new BigSequence()
x(5) = 1
x(63) = 1
x(64) = 1
println(x(5))
x(64) = 0
println(x)
}
}
8 提供一个Matrix类—你可以选择需要的是一个2*2的矩阵,任意大小的正方形矩阵,或m*n的矩阵。支持+和操作。操作应同样适用于单值,例如mat*2。单个元素可以通过mat(row,col)得到
class Matrix(val m: Int, val n: Int) {
private val value = Array.ofDim[Double](m, n)
def update(x: Int, y: Int, v: Double) = value(x)(y) = v
def apply(x: Int, y: Int) = value(x)(y)
def +(other: Matrix): Matrix = {
require(n == other.n)
require(m == other.m)
val res = new Matrix(m, n)
for (i <- 0 until m; j <- 0 until n) {
res(i, j) = this (i, j) + other(i, j)
}
res
}
def -(other: Matrix): Matrix = {
this + other * (-1)
}
def *(factor: Double): Matrix = {
val res = new Matrix(m, n)
for (i <- 0 until m; j <- 0 until n) {
res(i, j) = this (i, j) * factor
}
res
}
private def prod(other: Matrix, i: Int, j: Int) = {
(for (k <- 0 until n) yield value(i)(k) * other.value(j)(k)).sum
}
def *(other: Matrix) = {
require(n == other.m)
val res = new Matrix(m, other.n)
for (i <- 0 until m; j <- 0 until other.n) {
res(i, j) = prod(other, i, j)
}
res
}
override def toString = value.map(_.mkString(" ")).mkString("\n")
}
object Eight extends App {
val x = new Matrix(2, 2)
x(0, 0) = 1
x(0, 1) = 2
x(1, 0) = 3
x(1, 1) = 4
println(x)
println()
println(x * 2)
println()
println(x * 2 - x)
println()
println((x * 2) * (x * 3))
}
9 为RichFile类定义unapply操作,提取文件路径,名称和扩展名。举例来说,文件/home/cay/readme.txt的路径为/home/cay,名称为readme,扩展名为txt
class RichFile1(val path: String) {}
object RichFile1 {
def apply(path: String): RichFile1 = {
new RichFile1(path)
}
def unapply(richFile1: RichFile1) = {
if (richFile1.path == null) {
None
} else {
val reg = "([/\\w+]+)/(\\w+)\\.(\\w+)".r
val reg(r1, r2, r3) = richFile1.path
Some((r1, r2, r3))
}
}
}
object Nine {
def main(args: Array[String]) {
val richFile1 = RichFile1("/home/cay/readme.txt")
val RichFile1(r1, r2, r3) = richFile1
println(r1)
println(r2)
println(r3)
}
}
10 为RichFile类定义一个unapplySeq,提取所有路径段。举例来说,对于/home/cay/readme.txt,你应该产出三个路径段的序列:home,cay和readme.txt
class RichFile2(val path: String) {}
object RichFile2 {
def apply(path: String): RichFile2 = {
new RichFile2(path)
}
def unapplySeq(richFile2: RichFile2): Option[Seq[String]] = {
if (richFile2.path == null) {
None
} else {
if (richFile2.path.startsWith("/")) {
Some(richFile2.path.substring(1).split("/"))
} else {
Some(richFile2.path.split("/"))
}
}
}
}
object Ten {
def main(args: Array[String]) {
val richFile2 = RichFile2("/home/cay/readme.txt")
val RichFile2(r @ _*) = richFile2
println(r)
}
}