scala编程-学习笔记

 

https://www.cnblogs.com/fxjwind/p/3338829.html
//RUNOOB.com
http://www.runoob.com/scala/scala-functions.html
//API
https://docs.scala-lang.org/api/all.html
//
http://tool.oschina.net/apidocs
Chapter 2 Scala 入门		1
Chapter 3 Scala 入门(续)	1
Chapter 4 类和对象		1
Chapter 5 基础类型和操作	1
Chapter 6 函数式对象		1
Chapter 7 内建的控制结构	1
Chapter 8 函数和闭包		1
Chapter 9 抽象控制		1
Chapter 10 组合和继承		1
Chapter 11 scala的继承关系	1
Chapter 12 特质(trait)		1
Chapter 13 包和引入		1
Chapter 14 断言和测试		1
Chapter 15 样例类和模式匹配	1
Chapter 16 使用列表		1
Chapter 17 使用其他集合类	1	
Chapter 18 可变对象		1
Chapter 19 类型参数化		1
Chapter 20 抽象成员		1
Chapter 21 隐式函数和隐式参数	1
Chapter 22 实现列表		1
Chapter 23 重访for表达式	1
Chapter 24 深入集合类		1
Chapter 25 Scala集合		1
Chapter 26 提取器		1
Chapter 27 注解			
Chapter 28 使用XML		
Chapter 29 用对象实现模块化功能	
Chapter 30 对象相等性		
Chapter 31 结合Scala和Java	
Chapter 32 Future和并发编程	
Chapter 33 组合子解析器		
Chapter 34 GUI编程		
Chapter 35 Scells试算表
=============================================================Chapter 2 Scala 入门
//step1: scala 解释器
scala> 1+2
res1: Int = 3
scala> res1*2
res2: Int = 6

//step2: 定义变量
val m="Hello,scala world!"
res1: String = Hello,scala world!
-----------------------------------------
val	类java_final 变量:一经初始不可改变
var	非final变量:可变
-----------------------------------------
val m2: java.lang.String="its the second news!"
val m3: String="its the third news"
var gr="no Hello!"				//variable

//step3:定义函数

def max(x:Int,y:Int):		 		//函数体和参数
	Int={if (x<y) x else y}			//函数体(Int:返回类型)
def max(x:Int,y:Int)=if(x>y) x else y
def greet()=println("Hello,World")

//step4:编写Scala脚本
println("hello from a script")
$scala hello.scala
println("hello, "+args(0)+" ! ")
$ scala helloarg.scala planet
---Sc.scala
println("hello, "+args(0)+" ! ")
---
$ scala /home/lufax/桌面/Sc.scala zieox		 --->"jello zieox !"

//setp5: 用while做循环;用if做判断
//Sc.scala 数组版
var i=0
while (i<args.length){
	println("hello "+args(i)+" !") 
	i+=1
}

--->
var i=0
while (i<args.length){
	if(i !=0){print("");}
	println("hello "+args(i)+" !");
	i+=1
}
println();

//step6: 用foreach和for遍历
args.foreach(arg=>println(arg))
	scala /home/lufax/桌面/Sc.scala zieox jack ddd
===>
args.foreach((arg:String) => println(arg))

// '<-' the same as 'IN'
for (arg <- args) println(arg)

=============================================================Chapter 3 Scala 入门(续)
//step7: 用类型参数化数组
val big=new java.math.BigInteger("132456")

---------scala---------
val greetStrings=new Array[String](3) //创建长度为3的数组
greetStrings(0)="hello"
greetStrings(1)=" , "
greetStrings(2)="world!\n"
for (i<-0 to 2) print(greetStrings(i))

---------python---------
greetStrings=[]
for i in ["hello"," , ","world!"]:greetStrings.append[i]
for i in greetStrings:print(i)

-------------java-------------
public class Main {
    public static void main(String[] args) {
        List<String> greetStrings = new ArrayList<>();
        greetStrings.addAll(Arrays.asList("hello"," , ","world!"));
        greetStrings.add(" zie");
        greetStrings.stream().forEach(System.out::print);
    }
}
-------------------------------


greetStrings(0)="hello" 
<=>等价于
greetStrings.update(0,"hello")

--->
//初始化数组
val number=Array("one","two","three")
val number2=Array.apply("one","two","three")

//step8:使用列表
val onetwo=List(1,2)
val threefour=List(3,4)
//使用 ::: 来拼接List
val oneTofour=onetwo:::threefour
print("拼接后的 oneTofour: "+oneTofour)


//新建一个list:l
val l: List[Int] = List(-3, -2, 0, 1, 2, 3, 4)

//用 :: 来 add元素
5::threefour
---<output> List[Any] = List(4, 3, 5)
//用:+ 添加元素
threefour:+6
---<output> List[Any] = List(4, 3, 5, 6)
//Nil:空列表
val ot=1::2::3::Nil

//table 3.1 List的一些方法和用途 (list操作方法)
List / Nil								空列表
List("acc","ba","csss","asas")						list
val t="acc"::"ba"::"csss"::"asas"::Nil					list
t(2)									t中第3个元素值
t.count(s=>s.length==4)							count(s.length=4) s from t <Int = 2>
t.drop(2)								drop(第2位元素)
t.dropRight(2)								drop右边2个
t.exists(s=>s=="asas")							t中是否包含“asas”
t.filter(s=>s.length==4)						s筛选出length=4的<List[String] = List(csss, asas)>
t.forall(s=>s.endsWith("s"))						是否有结尾的<Boolean t= true>
t.foreach(s=>print(s+"\n"))						遍历打印t中元素
t.head()								首元素
t.init()								除尾元素的其他
t.isEmpty()								是否为空
t.last()								尾元素
t.length()								列表长度
t.map(s=>s+"y")								每一元素末尾+y
t.mkString(", ")							组合列表中元素在输出<String = acc , ba , csss , asas>
t.filterNot(s=>s.length==4 | s.length==2)				输出产度不等于4和2的值
t.reverse								倒序
//t.sort((s,t)=>s.charAt(0).toLower < t.charAt(0).toLower)		返回包括thrill列表所有元素,并且第一个字符小写按照字母顺序排列的列表(返回List("fill", "until", "Will"))	
t.tail									除首元素之外的其他元素


https://www.cnblogs.com/YaolongLin/p/5096687.html
//step9:使用 Tuple
val pair = (99, "Luftballons")
//访问tuple中元素
println(pair._1)
println(pair._2)


//step10: 使用 Set(集) 和 Map(映射)
var jetSet = Set("Boeing", "Airbus")
jetSet += "Lear"  /  jetSet=jetSet+"Lear"
println(jetSet.contains("Cessna"))

//Set
//import 可变set
import scala.collection.mutable
val ms=mutable.Set("hitch","Polyergeist")
ms+="Sherk"
println(ms)
//集合操作之:add
movieSet.+=("Serk")

//import 不可变set
import scala.collection.immutable.HashSet
val hs=HashSet("Thomas","fucks")
println(hs+"Coriander")


//Map
//import 可变Map
import scala.collection.mutable
--->new a Map
val tmp=mutable.Map[Int,String]()
tmp+=(1->"go and fuck")
tmp+=(2->"fuck and go")
tmp+=(3->"fuck")
//创建多维映射(i**i)
val tm=mutable.Map[Int,Map[Int,Int]]()
for (i <- 1 to 10) tm+=(i->Map(i->i*i))

//step11: 识别函数式编程风格
def printArgs(args:Array[String]): Unit={
	var i = 0
	while (i<args.length){
		println(args(i))
		i+=1
	}
}

--->
def printArgs(args:Array[String]): Unit={for (arg<-args){println(arg)}}
--->
def printArgs(args:Array[String]): Unit={args.foreach(println)}
---->//将列表中的值输出
def formatArgs(args:Array[String])=args.mkString("\n")

val res=formatArgs(Array("zero","one","two"))
---<output>---
res: String = zero one two


//step12: 从文件读取文本行
//执行file_println
import scala.io.Source
if (args.length>0){for (line<- Source.fromFile(args(0)).getLines()) println(line.length+" "+line)}
else Console.err.println("Please enter filename")

scala /home/lufax/桌面/Sc.scala /home/lufax/桌面/Sc.scala 
//将文本赋值给一个变量
val lines =Source.fromFile(args(0)).getLines().toList
def widthOfLength(s:String)=s.length.toString.length
//计算最大宽度
var maxWidth=0
for (line<-lines) maxWidth=maxWidth.max(widthOfLength(line))
//找出最大文本行
val longestLine=lines.reduceLeft((a,b)=>if (a.length>b.length) a else b)
val maxWidth=widthOfLength(longestLine)
//print 
for(line<-lines){
	val numSpace=maxWidth-widthOfLength(line)
	val padding=" " * numSpace
	println(padding+line.length+" | "+line)
}

-------------------------------------读取器---------------------------------------
import scala.io.Source
def widthOfLength(s:String)=s.length.toString.length
if (args.length>0){
	val lines =Source.fromFile(args(0)).getLines().toList
	val longestLine=lines.reduceLeft((a,b)=>if (a.length>b.length) a else b)
	val maxWidth=widthOfLength(longestLine)
	for(line<-lines){
		val numSpace=maxWidth-widthOfLength(line)
		val padding=" " * numSpace
		println(padding+line.length+" | "+line)
	}
}
else Console.err.println("Please enter filename")
---------------------------------------------------------------------------------



=============================================================Chapter 4 类和对象
//4.1 类,字段和方法
class a {var sum=0}	//创建类A
val b=new a		//创建引用
val c=new a
b.sum=11		//赋值
--->对于  v=new a 不能编译
--->we can peivate SUM
class aa{private var sum=0}
--->
class a {
	private var sum=0
	def add(b:Byte): Unit={sum+=b}
	def checksum():Int={return ~(sum & 0xFF)+1}
}
//创建一个累加器
--->
class a {
	private var sum=0
	def add(b:Byte) = sum+=b
	def checksum()= ~(sum & 0xFF)+1
}


//4.2 分号推断
val s="hello";println(s)

//4.3 单例对象
class ChecksumAccumulator {
	private var sum = 0
	def add(b: Byte) { sum += b }
	def checksum(): Int = ~(sum & 0xFF) + 1
}
import scala.collection.mutable
object ChecksumAccumulator{
	private val cache = mutable.Map.empty[String,Int]
	def calculate(s:String): Int=
		if (cache.contains(s)) cache(s)
		else{
			val acc=new ChecksumAccumulator
			for (c<-s) acc.add(c.toByte)
			val cs=acc.checksum()
			cache+=(s->cs)
			cs
		}
}

//4.4 scala 应用程序
import ChecksumAccumulator.calculate
object Summer{def main(args:Array[String])={for (arg<-args) println(arg+" : "+calculate(arg))}}


scalac /home/lufax/桌面/Sc.scala /home/lufax/桌面/Scc.scala
//启动守护进程
fsc /home/lufax/桌面/Sc.scala /home/lufax/桌面/Scc.scala
fsc -shutdown
//运行程序
scala /home/lufax/桌面/Scc.scala of love

//4.5 App特质
import ChecksumAccumulator.calculate
object FallWinterSpringSummer extends App{
	for (season<- List("fall","winter","spring")) println(season+" : "+calculate(season))	
}


=============================================================Chapter 5 基础类型和操作
//5.1 一些基础类型
Byte
Short
Int
Long
Char
String
Float
Double
Boolean

//5.2 字面量
//整数字面量
val hex =0x5			--->Int = 5
val hex2 = 0x00FF		--->Int = 255
val magic=0xcafebabe		--->Int = -889275714

val little:Short=367		--->little: Short = 367
val litter:Byte=28		--->litter: Byte = 28

//浮点数字面量
val big = 1.23464		--->big: Double = 1.23464
val bigger = 1.23464e1		--->bigger: Double = 12.3464
val biggerStill=123E45		--->biggerStill: Double = 1.23E47
val little =1.2345F 		--->little: Float = 1.2345
val litterBigger=3e5F		--->litterBigger: Float = 300000.0

//字符字面量
val a="A"			--->a: Char = A
val d='\u0041'			--->d: Char = A //对应16进制Unicode码
val f='\u0044'			--->f: Char = D
val B\u0041\u0044=1		--->BAD: Int = 1
val backlash='\\'		--->backlash: Char = \

//table5.2 特殊字符转义序列
\n				换行符
\b				退格符
\t				制表符
\f				换页符
\r				回车符
\"				双引号
\'				单引号
\\				反斜杠

//字符串字面常量
val hello="Hello"			--->hello: String = Hello
val escapes="\\\"\'"			--->escapes: String = \"'
//使用stripMargin去边
println("""|Welcome to Ultamix 3000.Type "HELP" for help.""".stripMargin)

//符号字面量
def updateRecordByName(r:Symbol,value:Any){}
val s='aSymbol				--->s: Symbol = 'aSymbol
val nm=s.name				--->nm: String = aSymbol

//符号值字面量
val bool = true				--->bool: Boolean = true
val fool = false			--->fool: Boolean = false


//5.3 字符串插值
val name = "reader"
println(s"Hello, $name!")		--->Hello, reader!

//使用$开始一个表达式
s"The answer is ${6*7}."		--->res9: String = The answer is 42.

println(raw"No\\\\escape!")

//f字符串插值
f"${math.Pi}%.5f"			--->res14: String = 3.14159
val pi ="Pi"
f"$pi is approximately ${math.Pi}%.8f." --->res18: String = PI is approximately 3.14159265.


//5.4 操作符即方法
val sum=1+2			--->sum: Int = 6
val sumMore=1.+(2)		--->sumMore: Int=3
val longSum=1+2L		--->longSum: Long=3
val s="Hello,World!"		--->s:String=Hello,World!
s indexOf 'o'			--->res19: Int = 4
//检索位置从第五位开始
s indexOf ('o',5)			--->res24: Int = 7
s.toLowerCase/s toLowerCase		--->res25: String = hello,world!

//5.5算术操作
3-1				--->res11: Int = 2
'b'-'a'				--->res12: Int = 1
2L*3L				--->res30: Long = 6
11/4				--->res31: Int = 2
11.0f/4.0f			--->res32: Float = 2.75
11.0%4.0			--->res33: Double = 3.0

//5.6关系和逻辑操作
(与and)&&  (或or)||  (亦或orelse)^

val a=true
val ques=a||!a					--->ques: Boolean = true
//短路
//执行 &&左侧 ||短路
def salt={println("salt");false}
def pepper={println("prepper");true}
salt && pepper			--->salt res6: Boolean = false
salt || pepper			--->salt pepper res7: Boolean = true

//5.7位运算符
与(&)	或(|)	非(^)
1 & 2				--->res9: Int = 0
1 | 2				--->res10: Int = 3
1 ^ 2				--->res11: Int = 3
~1				--->res12: Int = -2

<<  >> (十六进制移位符)
>>> (无符号右移)

//5.8对象相等性
("He"+"llo")="Hello"		--->res17: Boolean = true
//scala 与 java中的 == 不同:
java中比较值的相等性
scala中比较引用相等性(2个变量指向JVM的堆上的同一个对象)

//5.9操作符优先级和结合性
//table5.3 操作符优先级
* / %
+ -
:
= !
< >
&
^
|

a:::b:::c	<=>	a:::(b:::c)
a*b*c		<=>	(a*b)*c

//5.10 富包装类
//5.11 结语
0 max 10		--->res18: Int = 10
1 min 5			--->res19: Int = 1
-2.55 abs		--->res19: Double = 2.55
-5.88 round		--->res20: Long = -6
1.5 isInfinity		--->res21: Boolean = false
(1.0/0) isInfinity	--->res22: Boolean = true
4 to 10			--->res23: scala.collection.immutable.Range.Inclusive = Range 4 to 10
"bob" capitalize	--->res26: String = Bob
"robert" drop 2		--->res27: String = bert



=============================================================Chapter 6 函数式对象
//6.1 Rational 类的规格定义
有理数(rational number): n/d (n,d为整数 且 d!=0)
val onehalf=new Rational(1,2)
val twothird=new Rational(2,3)
(onehalf/7)+(1-twothird)

//构建Rational
class Rational(n:Int,d:Int){println("Created "+n+"/"+d)}
new Rational(1,2)

//6.3重新实现toString方法
class Rational(n:Int,d:Int){override def toString = n + "/" +d }
val x=new Rational(1,2)			---> res3: Rational = 1/2
val y=new Rational(3,4)

//6.4检查前置条件
val x=new Rational(1,0)			--->x: Rational = 1/0
//使用require参数(接受一个boolean参数)创建前置条件
class Rational(n:Int,d:Int){
	require(d != 0)
	override def toString=n+"/"+d
}

//6.5 添加字段
//给Rational添加add方法
class Rational(n:Int,d:Int){
	require	(d != 0)
	val number: Int=n
	val denom: Int=d
	override def toString=number+"/"+denom
	def add(that:Rational): Rational =
		new Rational(number*that.denom+that.number*denom,denom*that.denom)
}

val a=new Rational(1,2)
val b=new Rational(2,5)
a add b				--->res10: Rational = 9/10

--->python
def ra(a,b):
	if b == 0: print("can't divide ZERO")
	else:print(str(a)+"/"+str(b))
		
val r=new Rational(1,2)
r.number			--->res11: Int = 1
r.denom				--->res12: Int = 2

//6.6 自引用
def lessthan(that : Rational)=this.number*that.denom<that.number*this.denom
def max(that:Rational)=if (this.lessthan(that)) that else this 

//6.7 辅助构造方法 (auxiliary constructor)
def this(...)
//带有辅助构造方法的Rational
--->new Rational(2)			--->res15: Rational = 2/1

class Rational(n:Int,d:Int) {
	require(d != 0)
	val number: Int = n
	val denom: Int = d
	def this(n:Int)=this(n,1)			//辅助构造方法
	override def toString=number+"/"+denom		//override方法
	def add(that: Rational) : Rational =
		new Rational(number*that.denom+that.number*denom,denom*that.denom)
}

//6.8私有字段和方法
--->new Rational(22,4)			--->res16: Rational = 11/2
//添加公约数方法
class Rational (n:Int,d:Int){
	require(d != 0)
	private val g = gcd(n.abs,d.abs)
	val number = n / g
	val denom = d / g
	def this(n:Int) = this (n, 1)
	def add(that: Rational) : Rational = 
		new Rational(number*that.denom+that.number*denom,denom*that.denom)
	override def toString=number+"/"+denom
	private def gcd(a: Int,b: Int): Int = if (b==0) a else gcd(b,a%b)
}

//6.9 定义操作符
//添加 '+' 和 '*' 方法
class Rational (n:Int,d:Int){
	require(d != 0)
	private val g = gcd(n.abs,d.abs)
	val number = n / g
	val denom = d / g
	def this(n:Int) = this (n, 1)
	def + (that: Rational): Rational=new Rational(number*that.denom+denom*that.number,denom*that.denom)
	def * (that: Rational): Rational=new Rational(number*that.number,denom*that.denom)
	def add(that: Rational) : Rational = new Rational(number*that.denom+that.number*denom,denom*that.denom)
	override def toString=number+"/"+denom
	private def gcd(a: Int,b: Int): Int = if (b==0) a else gcd(b,a%b)
}

--------------------------test----------------------------
val a =new Rational(2,4)
val b=new Rational(1,3)
a+b				--->res29: Rational = 7/6
----------------------------------------------------------


//6.10 scala中的标识符
//操作标识符 + ++ ::: <?> :->
//混合标识符
//字面标识符 `...`


//6.11 方法重载
beacuse: val r = new Rational(2) ---> (can't) r*2
so: we make the Overload
class Rational (n:Int,d:Int){
	require(d != 0)
	private val g = gcd(n.abs,d.abs)
	val number = n / g
	val denom = d / g
	def this(n:Int) = this (n, 1)
	def + (that: Rational): Rational = new Rational(number*that.denom+denom*that.number,denom*that.denom)
	def - (that: Rational): Rational = new Rational(number*that.denom-denom*that.number,denom*that.denom)
	def - (i: Int): Rational = new Rational(number-i*denom,denom)
	def * (that: Rational): Rational=new Rational(number*that.number,denom*that.denom)
	def * (i: Int): Rational = new Rational(number*i,denom)
	def add(that: Rational) : Rational = new Rational(number*that.denom+that.number*denom,denom*that.denom)
	def / (that: Rational): Rational = new Rational(number*that.denom,denom*that.number)
	def / (i: Int): Rational = new Rational(number,denom*i)
	override def toString = number+"/"+denom
	private def gcd(a: Int,b: Int): Int = if (b==0) a else gcd(b,a%b)
}

--------------------------test----------------------------
val a =new Rational(2,4)
val b=new Rational(1,3)
a*2				--->res55: Rational = 1/1
a/2				--->res56: Rational = 1/4
2*a				--->error
----------------------------------------------------------

//6.12 隐式转换 详见CP21
//6.13 逐注意事项 P112
//6.14 结语

=============================================================Chapter 7 内建的控制结构
while try for match
//7.1 if 表达式
var fname="/home/lufax/桌面/ts.py"
if (!args.isEmpty) fname=args(0)
--->
val fname= if (!args.isEmpty) args(0) else "/home/lufax/桌面/ts.py"
--->scala_script
println(if (!args.isEmpty) args(0) else "/home/lufax/桌面/ts.py")

//7.2 while 循环
//变量var往往与while一同出现
def gcdloop(x:Int,y:Int): Long = {
	var a = x
	var b = y
	while (a!=0){val temp =1a = b % ab = temp}
	b
}
//do-while
var line=""
do {line=readLine();println("Read: "+line)}
while (line !="")
//
def greet() = {println("hi")}			--->greet: ()Unit
() == greet()					--->hi res11: Boolean = true

//7.3 for表达式
//7.3.1.遍历集合
val filehere=(new java.io.File(".")).listFiles		//Array[File]
for (file<-filehere) pritln(file)
//example:区间
for (i<-1 to 10) println(i*i)				//i in [1,10]
for (i<-1 until 10) println(i*i)			//i in [1-10)

//7.3.2.过滤
//example:取出某文件夹下的所有scala文件名
val filehere=(new java.io.File("/home/lufax/桌面")).listFiles
for (file <- filehere if file.getName.endsWith(".scala")) println(file)
===>
for (file<-filehere) if(file.getName.endsWith(".scala")) println(file)

//7.3.3.嵌套迭代
//example: for中嵌套多个生成器
def fileLines(file: java.io.File)=scala.io.Source.fromFile(file).getLines().toList
def grep(pattern: String)=
	for(
		file<-filehere
		if file.getName.endsWith(".scala");
		line<-fileLines(file)
		if line.trim.matches(pattern)
		) 
	println(file+" : "+line.trim)
	grep(".*gcd.*")

//7.3.4. 中途(mid-stream)变量绑定
def grep(pattern:String)= 
	for {
		file<-filehere
		if file.getName.endsWith(".scala")
		line<-fileLines(file)
		trimmed=line.trim
		if trimmed.matches(pattern)
		}println(file+" : "+trimmed)
grep(".*gcd.*")

//7.3.5. 产出一个新集合
//for - yield 表达式
for 子句 yield 代码体
//example
def scalafile= 
	for{
		file<-filehere
		if file.getName.endsWith(".scala")
	} yield file

---------output------------
scala> scalafile
res21: Array[java.io.File] = Array(/home/lufax/桌面/Scala.scala, /home/lufax/桌面/Sc.scala, /home/lufax/桌面/Scc.scala)
---------------------------

//example:在文件下查找scala文件,并计算其行长
val forlinelengths=
	for{
		file<-filehere
		if file.getName.endsWith(".scala")
		line<-fileLines(file)
		trimmed=line.trim
		if trimmed.matches(".*for.*")	
	} yield trimmed.length


//7.4用try表达式实现异常处理
//7.4.1 抛出异常
throw IllegalArgumentException
val half = if (n%2==0) n/2 else throw RuntimeException("n must be even")
//7.4.2 捕获异常
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {val f = new FileReader("input.txt")}
catch{
	case ex:FileNotFoundException => 	/...
	case ex:IOException			/...
}


//7.4.3 fianlly 子句
val file = new FileReader("input.txt")
try{}
finally{file.close()}

//7.4.4 交出值
def f(): Int = try return 1 finally return 2

import java.net.URL
import java.net.MalformedURLException
def urlFor(path:String)=try{new URL(path)}catch{case e: MalformedURLException => new URL("http://www.scala-lang.org")}

//7.5 match 表达式
val firstarg=if (args.length>0) args(0) else""
firstarg match{
	case "salt" => println("pepper")
	case "pepper" => println("salsa")
	case "chip" => println("cacom")
	case _ => println("huh?")
}
$:scala /home/lufax/桌面/Sc.scala "salt"	--->pepper

--->
val firstarg=if (!args.isEmpty) args(0) else""
val friend=
	firstarg match{
		case "salt" => println("pepper")
		case "pepper" => println("salsa")
		case "chip" => println("cacom")
		case _ => println("huh?")
}
println(friend)


// 7.6 没有break和continue的日子  (it's no break & continue)
//example:java
int i =0;
boolean foundit=false;
while (i<args.length){
	if(args[i].startsWith("-")){i=i+1;continue;}
	if(args[i].endsWith(".scala")){foundit=true;break;}
	i=i+1;
}

--->by scala
var i=0
var foundit=false
while(i<args.length && !foundit){
	if(!args(i).startsWith("-")){if(args(i).endsWith(".scala")) foundit = true}
	i=i+1
}

//example: searchFrom
def searchfrom(i:Int): Int=
	if (i >=args.length) -1
	else if (args(i).startsWith("-") searchfrom(i+1))
	else if (args(i).endsWith(".scala")) i
	else searchfrom(i+1)
val i = searchfrom(0)

//break类的break的方法
import scala.util.control.Breaks._
import java.io._
val in=new BufferedReader(new InputStreamReader(System.in))
breakable{while(true){println("? ");if (in.readLine()=="") break}}

//7.7 变量作用域
def printmultitable()={
  	var i=1
  	while (i<10){
    		var j = 1
    		while (j<10){
      			val prod=(i*j).toString
      			var k= prod.length
      			while (k<4){println(" ") ;k+=1}
      			print(prod)
      			j+=1
    	}
    	println()
    	i += 1
  }
}

//7.8 对指令式代码进行重构
//example:乘法表
def makeRowSeq (row: Int){
	for (col <- 1 to 10) yield{
		val pord=(row*col).toString
		val padding=" "*(4-prod.length)
		padding+prod
	}
def makeRow(row:Int)=makeRowSeq(row).mkString	
def multitable()={
	val tableSeq= //...	
	for (row <- 1 to 10) yield makeRow(row)
	tableSeq.mkString("\n")
}
	
//7.9 结语 P139



=============================================================Chapter 8 函数和闭包
//8.1 方法
//example1:读取文件中行长大于n的行
import scala.io.Source
object longlines{
	def processfile(filename: String,width: Int)={
		val source = Source.fromFile(filename)
		for (line <- source.getLines()) processline(filename,width,line)
	}
	private def processline(filename: String,width: Int,line: String)={
		if (line.length > width) println(filename+" : "+line.trim)
	}
}
------------------test---------------------
val a =longlines
s.processfile(/home/lufax/桌面/Sc.scala,10)
-------------------------------------------
//example2:finglonglines
object findlonglines {
	def main (args:Array[String]){
		val width = args(0).toInt
		for (arg<-args.drop(1)) longlines.processfile(arg,width)
	}
}

------------------------------------------test----------------------------------------------------
scala /home/lufax/桌面/scala/CP8/findlonglines.scala 10 /home/lufax/桌面/scala/CP8/longlines.scala
--------------------------------------------------------------------------------------------------


//8.2 局部函数
//example3:将processline方法添加到processfile方法中,被processfile私有化
def processfile(filename: String,width: Int)={
	def processline(filename:String,width:Int,line:String)={if (line.length>width) println(filename+" : "+line.trim)}
	val source = Source.fromFile(filename)
	for (line <- source.getLines()){processline(filename,width,line)}
}

//example4: 带有局部processline函数的longlines
import scala.io.Source
object longlines{
	def processfile (filename: String,Width: Int)={
		def processline(line: String)={if (line.length>width) println(filename+" : "+line.trim)}
		val source=Source.fromFile(filename)
		for (line <- source.getLines()) processline(line)
	}
}


//8.3 一级函数
//example: y=x^2+1
var f1 = (x:Int) => x*x+1			--->scala> f1(2)  --->res51: Int = 5

var f = (x:Int) =>{println("its");println("the");println("number of");x*x}
-----------tes--------
scala> f(11)
its
the
number of
res53: Int = 121
----------------------

val somenumber =List(-100,-50,-25,0,25,50,100,288)
//example: foreach
somenumber.foreach((x:Int)=>println(x))
//example: filter 
somenumber.filter((x:Int)=>x>0)

//example: foreach+filter
s.filter(x=>x>0).foreach(x=>println(x))
<=>
s.filter( _ >0).foreach(x=>println(x))
//8.4 函数字面量的简写形式
somenumber.filter((x)=>x>0)
somenumber.filter(x=>x>0)
somenumber.foreach(println _)
somenumber.foreach(x => println(x))
somenumber.foreach(println _)
somenumber.foreach(println)

//8.5 占位符语法
somenumber.filter( _ > 0)
//y=a*b+1
val f = ( _: Int) * (_: Int) +1

//8.6 部分应用函数
somenumber.foreach(println _)
somenumber.foreach(x => println(x))

def sum(x:Int,y:Int,z:Int)=x+y+z
//example: 赋值给a (函数赋值)
val a = sum _ 
a(1,2,3)	<===>	a.aplly(1,2,3)
//example: 创建一个单参数求和函数
val b = sum(1,_: Int,3)

//8.7 闭包
var more = 1
val addmore = (x:Int) => x + more
--->addmore(10)--->11
--->more=11--->addmore(10) --->21

//example: cumsum (foreach)
val somenumber =List(-100,-50,-25,0,25,50,100,288)
sum=0
somenumber.foreach(sum += _)

// example: y=x+b 函数
def makeincreaser(more: Int)=(x:Int)=>x+more

val inc1=makeincreaser(1)			//y=x+1
val inc99=makeincreaser(99)			//y=x+99

//8.8 特殊的函数调用形式
//8.8.1 可变参数 *
def echo(args: String*)=for (arg <- args) println(arg)

val arr=Array("it's","a","nice","day")
//对数组操作
echo(arr: _*)

//8.8.2 带名字的参数
def speed(distance:Float,time:Float):Float={distance/time}
val dis = List(1,2,13,14,51)
val tim = List(2,12,1,2,34,22)
echo(speed(dis: _*,tim: _*))

-------------------------------------tes-----------------------------------------
for (i<-dis) for (j<-tim) println(speed(time=i,distance=j))
for (i<= 0 until dis.length-1) println(speed(time=tim(i),distance=dis(i)))
---------------------------------------------------------------------------------

//8.8.3 缺省参数值
def printTime(out: java.io.PrintStream=Console.out) = out.println("time = "+System.currentTimeMillis())
def printTime2(out: java.io.PrintStream=Console.out,divisor: Int=1) = out.println("time = "+System.currentTimeMillis()/divisor)


//8.9 尾递归
def approximate(guess: Double): Double=
	if (isGoodEnough(guess)) guess
	else approximate(improve(guess))
--->
def approximateLoop(initialGuess:Double): Double={
	var guess= initialGuess
	while (!isGoodEnough(guess)) guess=improve(guess)
	guess
}

//8.9.1 跟踪尾递归函数
def boom(x: Int): Int={if (x==0) throw new Exception("boom!") else boom(x-1)+1}
def bang(x:Int): Int={if (x==0) throw new Exception("bang!") else bang(x-1)}

//8.9.2 尾递归的局限
def iseven(x:Int): Boolean=if (x==0) true else isOdd(x-1)
def isodd(x:Int): Boolean=if (x==0) false else iseven(x-1)

val sunvalue=nestedfun _
def nestedfun(x: Int): Unit={if (x != 0){println(x);funvalue(x-1)}}



=============================================================Chapter 9 抽象控制
//How does yield work?		https://docs.scala-lang.org/tutorials/FAQ/yield.html
//9.1 减少代码重复
//exampel:创建一个file后缀名匹配器 (文件名读取程序)
object filematcher{
	private def filehere=(new java.io.File("/home/lufax/桌面")).listFiles
	def filesending (query:String) = for (file<-filehere;if file.getName.endsWith(query)) yield file
	def filescontaining(query: String)=for (file<-filehere;if file.getName.contains(query)) yield file
	def fileregex(query: String)=for(file<-filehere;if file.getName.matches(query)) yield file
	def filesmatching(query: String,matcher:(String,String)=>Boolean)={for (file<-filehere;if matcher(file.getName,query)) yield file}
}

--->引入函数作为参数
def filesmatching(query:String,‘method’)=for (file<-filehere;if file.getName.‘method’(query) yield file)
--->
def filesmatching(query:String,matcher:(String,String)=>Boolean)={for (file<-filehere,if matcher(file.getName,query)) yield file}


==>调用filematcher	#创建(带参(函数))filematching方法,
def fileending(query:String)=filematcher.filesmatching(query,_.endsWith(_))		//第一个占位符_指代filename,第二个_ query
			  ~ =(filename:String,query:String)=>filename.endsWith(query)
def filecontianing(query:String)=filematcher.filesmatching(query,_.contains(_))
def fileregex(query:String)=filematcher.filesmatching(query,_.matches(_))


--->
object filematcher{
	private def filehere=(new java.io.File("/home/lufax/桌面")).listFiles
	private def filesmatching(matcher:String=>Boolean)=for (file <- filehere;if matcher(file.getName)) yield file
	def fileending(query:String)=filesmatching(_.endsWith(query))		//the same like =if file.getName.endsWith(query)
	def filecontianing(query:String)=filesmatching(_.contains(query))
	def fileregex(query:String)=filesmatching(_.matches(query))
}


// 9.2 简化调用方法
//example: >0 
def containeg(nums:List[Int]):Boolean={
	var exists=false
	for (num <- nums) if (num < 0) exists=true
	exists
}
---------------------------------------tes---------------------------------
containeg(List(12,3,4,2))			--->res: Boolean = false
---------------------------------------------------------------------------
===>升级版:函数式 *
def containeg(nums:List[Int])=nums.exists(_ < 0) 

//example: odd 判断是否时奇数
def containodd(nums:List[Int]):Boolean ={
	var exists=false
	for (num<-nums) if(num%2==0) exists=true
	exists
}
===>
def containodd(nums:List[Int])=nums.exists(_ % 2 == 1)


//9.3 柯里化 *
def plainsum(x:Int,y:Int)=x+y
--->
def curriedsum(x:Int)(y:Int)=x+y
val oneplus=curriedsum(1)_

--->函数入参
def first(x:Int)=(y:Int) => x+y
val second = first(1)

--->使用占位符curriedsum
val oneplus=curriedsum(1)_


//9.4 编写新的控制结构
//example:  2_twice op结构
def twice(op:Double=>Double,x:Double)=op(op(x))
--->
scala> twice(_ * 2,8)				--->res133: Double = 32.0 	*

//
def withprintwriter(file: File,op: PrintWriter => Unit) ={
	val writer = new PrintWriter(file)
	try {op(writer)}
	finally {writer.close()}
}
--->
withprintwriter(
	new File("date.txt")
	writer => writer.println(new java.util.Date)
)

//example:substring 	*
val g = "Hello , world"
g.substring(7,9)			---> val g = "Hello , world"

//使用贷出模式写入文件
def withprintwriter(file:File)(op:PrintWriter=>Unit) = {
	val writer = new PrintWriter(file)
	try{op(writer)}
	finally{writer.close()}
}
--->
val file=new File("data.txt")
withprintwriter(file) {writer=>writer.println(new java.util.Date)}

//9.5:=>传名参数
scala 传值参数和传名参数 ():=>和:=> :
https://blog.csdn.net/u010652576/article/details/48550651
http://scalagroup.group.iteye.com/group/topic/26303
//传名参数和传值参数
scala参数传递:	https://www.jianshu.com/p/9b9519a36d78
() => Unit			---> 是一个函数; 
   => Unit			---> 是一个执行结果为Unit的表达式

var assertionsEnabled=true
def myassert(predicate:()=>Boolean) = if (assertionsEnabled && !predicate()) throw new AssertionError

//使用传名参数
def bynameassert(predicate: =>Boolean) = if (assertionsEnabled && !predicate()) throw new AssertionError
def boolAssert(predicate:Boolean) = if (assertionsEnabled && !predicate()) throw new AssertionError


object FunctionTest2 {  
	def main(args: Array[String]) {  
		def test(code: => Unit) {  
			println("start")  
			code   
			println("end")}
		test {   
			println("when evaluated")  
			println("bb")}
		def test1(code: () => Unit) {  
			println("start")  
			code()    
			println("end")}  
        	test1 { 
			() =>  
				println("when evaluated")  
				println("bb")}  
	}  
}

------test-------
start
when evaluated
bb
end
start
when evaluated
bb
end
-----------------
// 这里说明了传名参数=>和零参数函数()=>的区别了,后者是参数函数先计算运行了返回()=>实例在传给test1的


=============================================================Chapter 10 组合和继承
//10.1 一个二维的布局类库
elem(s:String): Element
val col1=elem("hello") above elem("***")
val col2=elem("***") above elem("wd")
col1 beside col2
-------------------
hello ***
*** wd
-------------------

//10.2 抽象类
abstract class element{def contents:Array[String]}
#抽象类不可被实例化   --->error: new element

//10.3 定义无参方法 	*
abstract class element{
	def contents: Array[String]
	def height: Int=contents.length
	def width: Int=if (height==0) 0 else contents(0).length
}
---> //将height和weight转为字段
abstract class element{
	def contents: Array[String]
	val height=contents.length
	val width=if (height==0) 0 else contents(0).length
}

//10.4 扩展类
extends(继承)  &&  override(重写)  &&  implement(实现)
class arrayelement(conts:Array[String]) extends element{def contents:Array[String]=conts} //继承无参函数并创建引用 =
--->
val ae=new arrayelement(Array("hello","tuesday"))
ae.height			--->res19: Int = 2
ae.width			--->res20: Int = 5


//10.5 重写方法和字段
//用字段重写无参方法
class arrayelement(conts:Array[String]) extends element{val contents:Array[String]=conts}

#java中允许重载,而scala中不允许这样直接重名存在
class tets{private int f = 0;public int f(){return 88;}}

//10.6定义参数字段
class arrayelement(conts:Array[String]) extends element {val contents:Array[String]=conts}
//直接写入到参数中
===>
class arrayelement(val contents:Array[String]) extends element

//example:用override重写	*
class cat{val dangerous=false}
class tiger(override val dangerous:Boolean,private var age:Int) extends cat	//tiger带有重写的dangerious
===>
class tiger(param1:Boolean,param2:Int) extends cat{
	override val dangerous=param1
	private var age = param2
}


//10.7 调用超类构造方法	(父类参数=子类参数)	*
class lineelement(s:String) extends arrayelement(Array(s)){
	override def width = s.length
	override def height = s.length
}

element <- arrayelement <- lineelement   //use s(Array(s)) which from the arrayelement


//10.8 使用override修饰符   P190

//10.9 多态和动态绑定 P192
class uniformelement(ch:Char,override val width:Int,override val height:Int) extends element {
	private val line=ch.toString*width
	def contents=Array.fill(height)(line)}

--->
val e1: element=new arrayelement(Array("hello","wd"))
val ae: arrayelement=new lineelement("hello")
val e2: element=ae
val e3: element=new uniformelement("x",2,3)

--->
abstract class element {def demo()={println("Element's implementation invoked")}}
class arrayelement extends element {override def demo()={println("arrayelement's implementation invoked")}}
class lineelement extends arrayelement{override def demo()={println("lineelement's implementation invoked")}}
class uniformelement extends element

def i(e:element)={e.demo()}
--------------------------------------------test-----------------------------------------------------
scala> i(new arrayelement)				---> arrayelement's implementation invoked
scala> i(new lineelement)				---> lineelement's implementation invoked
scala> i(new uniformelement)				---> Element's implementation invoked
-----------------------------------------------------------------------------------------------------

//10.10 声明final成员
//demo() - final
class arrayelement extends element {final override def demo()={println("arrayelement's implementation invoked")}}
//class - final
final class arrayelement extends element {override def demo()={println("arrayelement's implementation invoked")}}

//10.11 使用组合和继承 P197
class lineelement(s:String) extends element{
	val contents=Array(s)
	override def width=s.length
	override def height=1
}

//10.12 实现above,beside和toString P198
def above(that:element):element=new arrayelement(this.contents ++ that.contents)
def beside(that:element):element={
	val contents = new Array[String](this.contents.length)
	for (i <- 0 until this.contents.length) contents(i)=this.contents(i)+that.contents(i)
	new arrayelement(contents)
}

new arrayelement(for ((line1,line2) <- this.contents zip that.contents) yield line1+line2)

//成对数组
scala> Array(1,2,3) zip Array("a","s")			---> res28: Array[(Int, String)] = Array((1,a), (2,s))


===>
abstract class element{
	def contents: Array[String]
	def width: Int = if(height==0) 0 else contents(0).length
	def height: Int = contents.length
	def above(that:element): element = new arrayelement(this.contents ++ that.contents)
	def beside(that:element): element = new arrayelement(for ((line1,line2) <- this.contents zip that.contents) yield line1+line2)
	override def toString=contents mkString "\n"
}


//10.13 定义工厂对象
//继承链 element <- arrayelement <- uniformelement
//element
abstract class element{
	def contents: Array[String]
	def height: Int=contents.length
	def width: Int=if (height==0) 0 else contents(0).length
}
//arrayelement
class arrayelement(val contents:Array[String]) extends element
//lineelement
class lineelement(s:String) extends arrayelement(Array(s)){
	override def width = s.length
	override def height = s.length
}
//uniformelement
class uniformelement(ch:Char,override val width:Int,override val height:Int) extends element {
private val line=ch.toString*width
def contents=Array.fill(height)(line)}

===>
//带有工厂方法的工厂对象
object element0 {
	def elem(contents:Array[String]):element=new arrayelement(contents)
	def elem(chr:Char,width:Int,height:Int): element=new uniformelement(chr,width,height)
	def elem(line:String): element = new lineelement(line)
}

===>
//重构后使用工厂方法的element对象
import element0.elem
abstract class element1 {
	def contents: Array[String]
	def width: Int = if (height==0) 0 else contents(0).length
	def height: Int = contents.length
	def above(that:element): element=elem(this.contents ++ that.contents)
	def beside(that:element): element=elem(for ((line1,line2) <- this.contents zip that.contents) yield line1+line2)
	override def toString=contents mkString "\n"
}


===>
//改进版element
object element3{
	private class arrayelement (val contents:Array[String]) extends element
	private class lineelement(s:String) extends element{
		val contents=Array(s)
		override def width=s.length
		override def height=1
	}
	private class uniformelement (u:Char,override val width:Int,override val height:Int) extends element{
		private val line=u.toString()*width
		def contents=Array.fill(height)(line)
	}
	def elem(contents:Array[String]):element= new arrayelement(contents)
	def elem(s:String):element=new lineelement(s)
	def elem(u:Char,width:Int,height:Int):element=new uniformelement(u,width,height)
}


---
//10.14 增高和增宽
import element3.elem
abstract class element3{
	def contents:Array[String]
	def width: Int=contents(0).length
	def height: Int=contents.length
	def above(that:element3):element3={
		val this1=this widen that.width
		val that1=that widen this.width
		elem(this1.contents ++ that1.contents)
		}
	def beside(that:element3):element3={
		val this1=this heighten that.height
		val that1=that heighten this.height
		elem(for ( (line1,line2) <- this1.contents zip that1.contents) yield line1+line2)
		}
	def widen(w:Int):element3=
		if (w<=width) this 
		else{
			val left = elem(' ',(w-width)/2,height)
			val right=elem(' ',w-width-left.width,height)
			left beside this beside right
			}
	def heighten(h : Int): element3 =
		if (h<=height) this
		else{
			val top=elem(' ',width,(h-height)/2)
			val bot=elem(' ',width,h-height-top.height)
			top above this above bot
			}
		override def toString = contents mkString "\n"
}

//10.15 put it together P206
import element.elem
object spiral{
val space = elem(" ")
val corner=elem("+")
def spiral(nedges:Int,direction:Int): element={
	if(nedges==1) elem("+")
	else{
		val sp=spiral(nedges-1,(direction+3)%4)
		def verticalbar=elem('|',1,sp.height)
		def horizontalbar=elem('-',sp.width,1)
		if(direction==0) (corner beside horizontalbar) above (sp deside space)
		else if(direction==1) (sp above space) beside (corner above verticalbar)
		else if(direction==2) (space beside sp) above (horizontalbar beside corner)
		else (verticalbar above corner) beside (space above sp)
		}
	}
def main(args:Array[String])={
	val nSides = args(0).toInt
	println(spiral(nSides,0))}
}

---> $ scala spiral 6   ~~~>



=============================================================Chapter 11 scala的继承关系
https://blog.csdn.net/dabokele/article/details/52746255

// 11.1 scala的类继承关系
final def ==(that:Any): Boolean
final def !=(that:Any): Boolean
def equals(that:Any):Boolean
def ##:Int
def hashCode:Int
def toString:String

//picture on P209 url above
//ex:
11.toString				--->res9: String = 11
11.hashCode				--->res10: Int = 11
11 equals 11				--->res11: Boolean = true

42 max 43				--->res2: Int = 43
42 min 43				--->res3: Int = 42
1 until 10				--->
1 to 10					--->res5: scala.collection.immutable.Range.Inclusive = Range 1 to 10
(-5).abs				--->res6: Int = 5


//11.2 基本类型的实现机制
对Java熟悉的话,应该会对int类型和Integer类型有一定的了解。
在Scala中对Int类型变量的处理也和Java中类似,Int类型提供加或乘这样的简单操作,
但如果需要调用toString方法或者将Int值赋给Any类型变量时,Int型变量会自动转化成Integer类型。
这个过程和Java中的自动装箱有些类似。 
我们首先看一下下面这段Java代码
boolean isEqualInt(int x, int y) {return x == y;}
System.out.println(isEqual(421, 421));
boolean isEqualInteger(Integer x, Integer y) {return x == y;}
System.out.println(isEqualInteger(421, 421));

//by_scala
def isequal(x:Int,y:Int)=x==y
def isequal(x:Any,y:Any)=x==y
-----------------------------
val x = "abcd".substring(2)
val y = "abcd".substring(2)
-----------------------------
scala> x==y
res13: Boolean = true
-----------------------------

//== 与 equal
val x = new String("abc")
val y = new String("abc")
#类似java的equal,java中==判断的是引用相等性 并不是值相等性
scala> x eq y				--->res14: Boolean = false 		
scala> x ne y				--->res16: Boolean = true
				

//11.3 底类型(bottom types)
scala.Null & scala.Nothing
//ex
def error(message: String): Nothing=throw new RuntimeException(message)
def devide(x:Int,y:Int)=if (y!=0) x/y else error("can't devide by zero")


//11.4 定义自己的值类型
class dollars(val amount: Int) extends AnyVal{override def toString()="$"+amount}
val m=new dollars(100)				--->m: dollars = $100
scala> m.amount					--->res20: Int = 100

class swissfrancs(val amount:Int) extends AnyVal{override def toString()=amount+" CHF"}
scala> new swissfrancs(10)			--->res0: swissfrancs = 10 CHF

//避免类型单一化
def title(text:String,anchor:String,style:String):String=s"<a id='$anchor'><h1 class='$style'>$text</h1></a>"
-------------------------------------------------------------------------
scala> title("chap:vcls","bold","Value Classes")
res6: String = <a id='bold'><h1 class='Value Classes'>chap:vcls</h1></a>
-------------------------------------------------------------------------
--->
class anchor(val value:String) extends AnyVal
class style(val value:String) extends AnyVal
class text(val value:String) extends AnyVal
class html(val value:String) extends AnyVal

def title(text:String,anchor:String,style:String):html=new html(s"<a id='${anchor.value}'>"+s"<h1 class='${style.value}'>"+text.value+"</h1></a>")
<error>---title(anchor("chap:vcls"),new style("bold"),new text("value classes"))



=============================================================Chapter 12 特质 trait
//12.4 trait 如何工作(with,extends)
trait phi{ def philize()={println("its,good")}}
class forg extends phi{override def toString="green"}
--->
scala> val frog=new forg			--->frog: forg = green
scala> frog.philize()				--->its,good
--->
val p:phi=frog
scala> p.philize()				--->its,good

//use with 
class animal{def legs(a:Int)={"it has "+a+" legs"}}
class frog extends animal with phi{override def toString="green"}
--->
val a=new frog()
scala> a.philize()				--->its,good
//use 2 traits		*
trait hasdicks{
	def eggs()={println("2 eggs")}
	def dick()={println("one dick")}
}
class cow extends animal with phi with hasdicks {override def toString="Black"}
--->
scala> val c =new cow				--->c: cow = Black
scala> c.eggs()					--->2 eggs

//override philize(对phi中的philize重写)
class frog extends animal with phi{
	override def toString="green"
	override def philize()={println("its always good")}
}
--->
val f:phi=new frog
scala>f.philize					---->its always good

#1.特质不能有任何类参数		*
#2.类和特质的区别:类中的super调用时静态绑定的,而trait中的super是动态绑定的		*


//12.2 瘦接口和富接口
//比较贫瘠的接口通过trait变为富接口
trait charsequence{
	def charAt(index:Int):Char
	def length:Int
	def subSequence(start:Int,end:Int):charsequence
	def toString():String
}

//12.3 示例:矩阵对象
//传入类作为calss的入参
class point(val x:Int,val y:Int)
class rectangle(val topleft:point,val bottomright:point){
	def left=topleft.x
	def right=bottomright.x
	def width=right-left
}
--->
abstract class component{
	def topleft:point
	def bottomright:point
	def left =topleft.x
	def right =bottomright.x
	def width =right-left
}
--->改写成trait
trait rectangular{
	def topleft:point
	def bottomright:point
	def left =topleft.x
	def right =bottomright.x
	def width =right-left
}
-->通过trait实现component
abstract class component extends rectangular{}
--->
class rectangle(val topleft:point,val bottomright:point) extends rectangular{}
-------------------------------test--------------------------------
val rect= new rectangle(new point(1,1),new point(10,10))
scala> rect.left				--->res4: Int = 1
scala> rect. width				--->res6: Int = 9
-------------------------------------------------------------------

//12.4 Ordered 特质
----------------------------------------use rational----------------------------------------
class Rational (n:Int,d:Int){
	require(d != 0)
	private val g = gcd(n.abs,d.abs)
	val number = n / g
	val denom = d / g
	def this(n:Int) = this (n, 1)
	def + (that: Rational): Rational=
		new Rational(number*that.denom+denom*that.number,denom*that.denom)
	def - (that: Rational): Rational=
		new Rational(number*that.denom-denom*that.number,denom*that.denom)
	def - (i: Int): Rational=new Rational(number-i*denom,denom)
	def * (that: Rational): Rational=new Rational(number*that.number,denom*that.denom)
	def * (i: Int): Rational=new Rational(number*i,denom)
	def add(that: Rational) : Rational = 
		new Rational(number*that.denom+that.number*denom,denom*that.denom)
	def / (that: Rational): Rational=
		new Rational(number*that.denom,denom*that.number)
	def / (i: Int): Rational= new Rational(number,denom*i)
	override def toString=number+"/"+denom
	private def gcd(a: Int,b: Int): Int = if (b==0) a else gcd(b,a%b)
}
-------------------------------------------------------------------------------------------
//单调添加><=方法
...
def < (that:Rational)=this.number*that.denom<that.number*this.denom
def > (that:Rational)=that<this
def <= (that:Rational)=(this<that) || (this==that)
def >= (that:Rational)=(this>that) || (this==that)
...


//by Ordered 混入ordered特质
class Rational(n:Int,d:Int) extends Ordered[Rational]{
...
def compare(that:Rational)=(this.number*that.denom)-(that.number*this.denom)
}

---------------------------------------------------------------------------------------------------->
class Rational(n:Int,d:Int) extends Ordered[Rational]{
	require(d != 0)
	private val g = gcd(n.abs,d.abs)
	val number = n / g
	val denom = d / g
	def this(n:Int) = this (n, 1)
	def + (that: Rational): Rational=
		new Rational(number*that.denom+denom*that.number,denom*that.denom)
	def - (that: Rational): Rational=
		new Rational(number*that.denom-denom*that.number,denom*that.denom)
	def - (i: Int): Rational=new Rational(number-i*denom,denom)
	def * (that: Rational): Rational=new Rational(number*that.number,denom*that.denom)
	def * (i: Int): Rational=new Rational(number*i,denom)
	def add(that: Rational) : Rational = 
		new Rational(number*that.denom+that.number*denom,denom*that.denom)
	def / (that: Rational): Rational=
		new Rational(number*that.denom,denom*that.number)
	def / (i: Int): Rational= new Rational(number,denom*i)
	override def toString=number+"/"+denom
	private def gcd(a: Int,b: Int): Int = if (b==0) a else gcd(b,a%b)
	def compare(that:Rational)=(this.number*that.denom)-(that.number*this.denom)
}
----------------------------------------------------------------------------------------------------
-------------------------------------------------test-----------------------------------------------
val half= new Rational(1,2)
val third = new Rational(1,3)
scala> third>half				--->res7: Boolean = false
----------------------------------------------------------------------------------------------------

//12.5 作为可叠加修改的特质
abstract class Intqueue{
	def get():Int
	def put(x:Int)
}

//私有字段缓冲组
import scala.collection.mutable.ArrayBuffer
class basicintqueue extends Intqueue{
	private val buf = new ArrayBuffer[Int]
	def get()=buf.remove(0)
	def put(x:Int)={buf+=x}
}

//可叠加修改的特质doubling
trait doubling extends Intqueue{abstract override def put(x:Int)={super.put(2*x)}}

class myqueue extends basicintqueue with doubling
val q=new myqueue
q.put(10)
q.get()						--->res22: Int = 20
--->
//使用new实例化
val q = new basicintqueue with doubling
q.put(10)
q.get()						--->res23: Int = 20

//实现 incrementing & filtering
trait incrementing extends Intqueue{abstract override def put(x:Int)={super.put(x+1)}}
trait filtering extends Intqueue{abstract override def put(x:Int)={if(x>=0) super.put(x)}}

val q=(new basicintqueue with incrementing with filtering)	//右先执行
q.put(-1);q.put(0);q.put(1)
queue.get()					--->res38: Int = 1
queue.get()					--->res39: Int = 2
#首先执行filtering特质 滤除 filtering( < 0 ) 后 incrementing

val q=(new basicintqueue with filtering with incrementing)
q.put(-1);q.put(0);q.put(1)
queue.get()					--->res50: Int = 0
queue.get()					--->res51: Int = 1
queue.get()					--->res52: Int = 2

//12.6 why not 多继承 P234
val q = new basicintqueue with incrementing with doubling
scala> q.put(22)
scala> q.get()					--->res53: Int = 45

/*
trait myqueue extends basicintqueue with incrementing with doubling{
	def put(x:Int)={
		incrementing.super.put(x)
		doubling.super.put(x)
	}
}
*/
//线性化
class animal
trait furry extends animal
trait haslegs extends animal
trait fourlegged extends haslegs
class cat extends animal with furry with fourlegged

//当这些类和特质中的任何一个通过super调用某个方法时,被调用的时在线性化链条中的出现在其右侧的首个实现。
cat -> fourlegged -> haslegs -> furry -> animal -> AnyRef -> Any

//12.7 trait Or Not P238
#如果某个行为不会被复用,用具体类
#如果某个行为被用于多个互补相关的类,用trait
#如果想要从java代码中继承某个行为,用抽象类


=============================================================Chapter 13 包和引入
//13.1 put code to package
//example:
package bobsrockets.nav{class navi}

package bobsrockets{
	package nav{
		class navi
		package test{class navs}
	}
}

//13.2 相关代码的精简访问
package bobsrockets{
	package navigation{
		class navigator{val map=new starmap}
		class starmap
	}
	class ship{val nav=new navigation.navigator}
	package fleets{class fleet{def addship()={new ship}}}
}

//访问隐藏的包
package launch {class booster3}
package bobsrockets{
	package navigation{
		package launch{class booster1}
		class missioncontrol{
			val booster1=new launch.booster1
			val booster2=new bobsrockets.launch.booster2
			val booster3=new _root_.launch.booster3}		//_root_ (顶层包)
	}
	package launch {class booster2}
}

//13.3 引入 import
------------------------------------------------------------
package bobsdelights
abstract class fruit(val name:String,val color:String)
object fruit{
	object apple extends fruit("apple","red")
	object orange extends fruit("orangle","orange")
	object pear extends fruit("pear","yellowish")
	val menu=List(apple,orange,pear)
}
------------------------------------------------------------
import bobsdelights.fruit
import bobsdelights._
import bobsdelights.fruit._
------------------------------------------------------------

//import on need
def show(fruit:fruit)={
	import fruit._
	println(name+"'s are"+color)
}

#与java相比scala的import可以
1.出现在任意位置
2.引用对象(不论单列还是常规对象),而不只是包
3.让你重命名并隐藏某些被引入的成员

//直接导入包方法
import java.util.regex
class star{val pat=regex.Pattern.compile("a*b")}

//引入选择器子句	*
import fruit.{apple,orange}
import fruit.{apple=>McIntosh,orangle}
import java.{sql=>s}	//引入java.sql包 以S为名
import fruit.{_}	//import all
import fruit.{apple=>McIntosh,_}	//import all & named as McIntosh
import fruit.{pear=>_,_}		//import all except pear

#引入选择器可以包含
名称		x		import x
重命名子句	x=>y		import X (name as) Y
隐藏子句	x=>_		import * except x


//13.4 隐式引入
import java.lang._
import scala._
import Predef._

//13.5 访问修饰符
//private:私有成员
class outer {
	class inner {
		private def f()={println("f")}
		class InnerMost{f()}
	}
}

//proteced:受保护成员
package p{
	class super{protected def f()={println("f")}}
	class sub extends super {f()}
	class other {//(new super).f()}
}

//public:公共成员
package bobsrockets
package navigation{
	private[bobsrockets] class navigator{
		protected[navigation] def useStarChart()={}
		class legofjourney{private[navigator] val distance=100}
		private[this] var speed=200
	}
}
package launch{
	import navigation._
	object vehicle{private[launch] val guide=new navigator}
}


//保护范围
private[X]	//上至X都是私有的
private[this]	//仅当前可访问


//可见性和伴生对象
//example:类和伴生对象之间的私有成员互访
class rocket {
	import rocket.fuel
	private def canGoHomeAgain=fuel>20
}
object rocket{
	private def fuel=10
	def choosestrategy(rocket:rocket)={if (rocket.canGoHomeAgain) gohome() else pickastar()}
	def gohome()={}
	def pickastar()={}
}

//13.6 包对象
//example:
package printmenu
import bobsdelights.fruits
import bobsdelights.showfruit
object printmenu{def main(args:main[String]){for(fruit<-fruits.menu){showfruit(fruit)}}}



=============================================================Chapter 14 断言和测试
http://www.scalatest.org/getting_started_with_fun_suite
http://doc.scalatest.org/1.8/org/scalatest/FunSuite.html

//14.1 断言
assert(condition)
assert(condition,explanation)

//example:use assert 
def above(that:element):element={
	val this1=this widen that.width
	val that1=that widen this.width
	assert(this1.widdth=that1.width)
	elem(this1.contents+that1.contents)
}

//example:use ensuring
private def widen(w:Int):element=
	if(w<=width) this
	else{
		val left =elem(' ',(w-width)/2,height)
		var right=elem(' ',w-width-left.width,height)
		left beside this beside right
	} ensuring(w<=_.width)

//14.2 用scala写测试
//example:elementsuite
import org.scalatest.FunSuite
import element
class elementsuite extends FunSuite{
	test("elem result should have passed width"){
		val ele=elem('x',2,3)
		assert(ele.width==2)
	}
}


//14.3 失败报告
http://www.scalatest.org/

------------------test----------------------
val a = 3
scala> assert(A==2)
--------------------------------------------
java.lang.AssertionError: assertion failed
  at scala.Predef$.assert(Predef.scala:204)
  ... 28 elided
--------------------------------------------

//
assert(List(1,2,3).contains(4))
scala> assert(List(1,2,3).contains(4))
--------------------------------------------
java.lang.AssertionError: assertion failed
  at scala.Predef$.assert(Predef.scala:204)
  ... 28 elided
--------------------------------------------

//other methods
assertResult(2){ele.width}					//if ele.width==3 ===> “expected 2 , but got 3”
assertThrows[IllegalArgumentException]{elem('x',-2,3)}		//检查某个方法抛出预期异常

val caught=intercept[ArithmeticException]{1/0}
assert(caught.getMessage=="/ by zero")


//14.4 作为规格说明的测试 P263
//example:  用scalatest的FlatSpec描述并测试代码行为
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import element.elem
class elementspec extends FlatSpec with Matchers{
	"A UniformElement" should " have a width equal to the passed value" in {
		val ele=elem('x',2,3)
		ele.width should be (3)
		}
	it should "have a height equal to the passed value" in{
		val ele=elem('x',2,3)
		ele.height should be (3)
		}
	it should "throw an IAE if passed a negative width " in{
		an [IllegalArgumentException] should be thrownBy{elem('x',2,3)}
		}
}

--->
(new elementspec).execute()

//example: 用spec框架描述并测试代码行为
import org.specs2._
import element.elem
object elementspecification extends specification {
	"A UniformElement" should{
		"have a width equal to the passed value" in{
			val ele = elem('x',2,3)
			ele.width must be_==(2)}
		"have a height equal to the passed value" in{
			val ele = elem('x',2,3)
			ele.height must be_==(3)}
		"throw an IEA if passed a negative width" in{elem('x',-2,3) must trowA[IllegalArgumentException]}
	}
}

//example:用测试在联系人之间沟通
import org.scalatest._
class TVSetSpec extends FeatureSpec with GivenWhenThen{
	feature("TV power button"){
		scenario("User presses power button when TV is off"){
			Given("a TV set that is switched off")
			When("then power button is pressed")
			Then("the TV should switch on")
			pending
		}
	}
}


//14.5 基于性质的测试
//example:ScalaCheck
import org.scalatest.WordSpec
import org.scalatest.prop.PropertyChecks
import org.scalatest.MustMatchers._
import element.elem
class elementspec extends WordSpec with PropertyChecks{
	"elem result" must{"have passed with" in {forAll{(w:Int)=>whenever (w>0){elem('x',w,3).width must equal (w)}}}}}
#whenever: 只要左边为true右边必须为 true 

//14.6 组织和运行测试 P268




=============================================================Chapter 15 样例类和模式匹配
//15.1 a simple example
abstract class expr
	case class Var(name:String) extends expr
	case class number(num:Double) extends expr
	case class unop(operator:String,arg:expr) extends expr
	case class binop(operator:String,left:expr,right:expr) extends expr
//样例类
val v=Var("x")
val op=binop("+",number(1),v)
-------------------------------------test----------------------------------------
scala> v.name					--->res99: String = x
scala> op.left					--->res100: expr = number(1.0)
scala> println(op)				--->binop(+,number(1.0),Var(a))
scala> op.right==Var("a")			--->res104: Boolean = true
---------------------------------------------------------------------------------
scala> op.copy(operator="-")			--->res105: binop = binop(-,number(1.0),Var(a))

//模式匹配
//例:
unop("-",unop("-",e)) => e
binop("+",number(0)) => e
binop("*",number(1)) => e

//example:simplifytop
def simplifytop(expr:expr):expr=
	expr match{
		case unop("-",unop("-",e)) => e
		case binop("+",e,number(0)) => e
		case binop("*",e,number(1)) => e
		case _ => expr
}

scala> simplifytop(unop("-",unop("-",Var("x"))))			--->res107: expr = Var(x)

//构造方法模式
unop("-",unop("-",e))

//对比match和switch
//带空的默认样例模式匹配
expr match {case binop(op,left,right)=>println(expr," id a binary operation");case _ => }

//15.2 模式的种类
//1.通配模式 (_)
expr match{case binop(op,left,right)=>println(expr+" is a binary operation ");case _ => }
--->
expr match{case binop(_,_,_)=>println(expr+" is a binary operation ");case _ => println("it's something else ")}

//2. 常量模式 (int,Boolean,String...)
def desc(x:Any)=x match{
	case 5 => "five"
	case true => "truth"
	case "hello" =>"fuck u"
	case Nil => "the empty list"
	case _ => "something else "
}
----------------------------------------test------------------------------------
scala> desc(5)					--->res111: String = five
scala> desc(true)				--->res112: String = truth
--------------------------------------------------------------------------------

//3. 变量模式
expr match {case 0 =>"zero";case somethingelse => "not zero: " +somethingelse}
--->
var somethingelse = 2
def tes(a:Int)=a match{case 0 =>"zero";case somethingelse => "not zero: " +somethingelse}
--->
scala> tes(2)					--->res118: String = not zero: 2
--------------------------------------------------------------------------------

import math.{E,Pi}
E match {case Pi => "strange math ? Pi="+Pi;case _ => "OK"}
val pi=math.Pi
E match {case po=>"strange math? Pi= "+pi}

#变量模式中不能添加默认case
E match {case pi=>"strange math? Pi= "+pi;case _ => "OK"}		===>ERROR
//将pi转为常量
E match {case `pi`=>"strange math? Pi= "+pi;case _ => "OK"}


//4.构造方法模式
//example:
expr match{case binop("+",e,number(0))=>println("a deep match");case _ => }

//5.序列模式
//example:定长序列模式
expr match{case List(1,_,_) => println("found it ");case _ => }

//example:任意长度序列模式
expr match {case List(0,_*)=>println("found it");case _ => }

//6.元祖模式
def tup(expr:Any)=expr match {case (a,b,c)=>println("matched "+a+b+c);case _ =>}

//7.带类型的模式
def gz(x:Any)=x match{case s:String=>s.length;case m:Map[_,_]=>m.size;case _ => }
scala> gz(Map(1->'a',2->'b'))				--->res136: AnyVal = 2

//强制类型转换
expr.isInstanceOf[String]		//检查类型是否匹配
expr.asInstanceOf[String]		//强制类型装换

//example:isInstanceOf和asInstanceOf的不良风格
if (x.isInstanceOf[String]){
	val s=x.asInstanceOf[String]
	s.length
} else ...

//类型擦除
//默认情况下 非受检情况系统会提示(如下示列)
def isIntIntMap(x:Any)=x match{case m:Map[Int,Int]=>true;case _ => false}
scala> isIntIntMap(Map(1->2))				--->res11: Boolean = true
scala> isIntIntMap(Map("ss"->"s"))			--->res12: Boolean = true
//传入默认受检
def isStringArray(x:Any)=x match{case a:Array[String]=>"yes";case _ => "no"}

//变量绑定 @
//example: 带有变量绑定的模式(by@)
expr match{case unop("abs",e @ unop("abs", _ ))=> e ;case _ => }


//15.3 模式守卫
binop("+",Var("x"),Var("x"))			--->res18: binop = binop(+,Var(x),Var(x))
===>
binop("*",Var("x"),number(2))			--->res22: binop = binop(*,Var(x),number(2.0))

//example:带模式守卫的match表达式
def simplifyadd(e:expr) = e match {case binop("+",x,y) if x==y => binop("*",x,number(2)) ;case _ => e}
scala> simplifyadd(binop("+",Var("x"),Var("x")))		--->res23: expr = binop(*,Var(x),number(2.0))

//EX
case n:Int if 0<n => ...
case s:String if s(0)=="a" => ...


//15.4 模式重叠 P287
//example:样列顺序敏感的match表达式
def simplifyall (expr:expr):expr=expr match{
	case unop("-",unop("-",e))=>simplifyall(e)
	case binop("+",e,number(0))=>simplifyall(e)
	case unop(op,e)=>simplifyall(e)
	case binop(op,l,r) => binop(op,simplifyall(l),simplifyall(r))
	case _ => expr
}

//15.5 密封类 sealed
sealed abstract class expr
	case class Var(name:String) extends expr
	case class number(num:Double) extends expr
	case class unop(operator:String,arg:expr) extends expr
	case class binop(operator:String,left:expr,right:expr) extends expr

//example:
def desc(e:expr): String = e match{ case number(_)=>"a number!";case Var(_)=>"a variable";case _ => throw new RuntimeException}
scala> desc(number(1.131))			--->res3: String = a number!
scala> desc(Var("x"))				--->res4: String = a variable

===>//通过 @unchecked注解 轻便化
def desc(e:expr):String=(e: @unchecked) match {case number(_)=>"a number!";case Var(_)=>"a variable"}


//15.6 Optional 类
val capitals=Map("china"->"shanghai","japan"->"tokyo")
scala> capitals get "china"				--->res5: Option[String] = Some(shanghai)
scala> capitals get "usa"				--->res0: Option[String] = None

//用模式匹配将可选值解开
def show(x:Option[String])=x match{case Some(s)=>s;case None=>"what the fuck ? "}
scala> show(capitals get "shanghai")			--->res5: String = "what the fuck ? "


//15.7 到处都是模式
//15.7.1 变量定义中的模式
//example:用单个赋值定义多个变量
val mytup=(123,"asd")
val (number,string)=mytup
&
val exp=new binop("+",number(5),number(1))
val binop(op,left,right)=exp

//15.7.2 作为偏函数的case序列
val withdefault: Option[Int] => Int ={case Some(x)=>x;case None=>0}

var sum=0
def receive={
	case Data(byte)=>sum+=byte
	case GetChecksum(requester)=>val checksum=~(sum&0xFF)+1
	requester ! checksum
}

//偏函数写法
val second:List[Int]=>Int={case x :: y :: _ =>y}
val second:PartialFunction[List[Int],Int]={case x :: y :: _ => y}
//isDefinedAt 方法
second.isDefinedAt(List(5,6,7))

new PartialFunction[Listp[Int],Int]{
	def apply(xs:List[Int])=xs match{case x :: y :: _ _ => y}
	def isDefinedAt(xs:List[Int])=xs match{case x :: y :: _ => true ;case _ =>false}
}

//for 表达式中的模式
//example: for(tup) Expr
for ((country,city) <- capitals) println("the captial of "+country+" is "+city)
val results=List(Some("apple"),None,Some("orange"))
for (Some(fruit)<-results) println(fruit)


//15.8 一个复杂的例子 P298
//example: (x+y)*z+1
binop("+",binop("*",binop("+",Var("x"),Var("y")),Var("z")),number(1))

//package org.stairwaybook.expr
//import  org.stairwaybook.layout.Element.elem

sealed abstract class expr
	case class Var(name:String) extends expr
	case class number(num:Double) extends expr
	case class unop(operator:String,arg:expr) extends expr
	case class binop(operator:String,left:expr,right:expr) extends expr
class exprformatter{
	private val opgroups=Array(
				Set("|","||")Set("&","&&"),
				Set("^"),Set("==","!="),
				Set("<","<=",">",">="),
				Set("+","-"),Set("*","%"))
	private val precedence={val assocs=for {i <- 0 util opgroups.length;op <- opgroups(i)} yield op->i ;assocs.toMap}
	private val unaryPrecedence=opgroups.length
	private val fractionPrecedence=-1

	private def format(e:expr,enclPrec:Int):element=
		e match {
			case Var(name)=>elem(name)
			case number(num) => 
					def stripDot(s:String) 
						if (s endsWith ".0") s.substring(0,s.length-2)
						else s
					elem(stripDot(num.toString))
			case unop(op,arg)=>elem(op) beside format(arg,unaryPrecedence)
			case binop("/",left,right)=>
				val top=format(left,fractionPrecedence)
				val bot=format(right,fractionPrecedence)
				val line=elem("-",top.width max bot.width,1)
				val frac=top above line above bot
				if (enclPrec != fractionPrecedence) frac
				else elem(" ") beside frac beside elem(" ")
			case binop(op,left,right)=>
				val opPrec=precedence(op)
				val l=format(left,opPrec)
				val r=format(right,opPrec+1)
				val oper = l beside elem(" "+op+" ") beside r
				if (enclPrec <= opPrec) oper
				else elem("(") beside oper beside elem(")")
			}
	def format(e:expr):element=format(e,0)
}

//exprformatter: 演示程序
import org.stairwaybook.expr._
object Express extends App{
	val f = new ExprFormatter
	val e1=binop("*",binop("/",number(1),number(2)),binop("+",Var("x"),number(1)))
	val e2=binop("+",binop("/",Var("x"),number(2)),binop("/",number(1.5),Var("x"))
	val e3=binop("/",e1,e2)
	def show(e:expr)=println(f.format(e)+"\n\n")
	for (e<-Array(e1,e2,e3)) show(e)
}



=============================================================Chapter 16 使用列表
//16.1 List字面量
val fruit=List("apple","banana","sealfruit","orange")
val num=List(1,2,3,4,5)
val d3=List(List(1,0,0),List(0,1,0),List(0,0,1))
val empty=List()

//16.2 List 类型
val fruit:List[String]=List("apple","banana","sealfruit","orange")
val num:List[Int]=List(1,2,3,4,5)
val d3:List[List[Int]]=List(List(1,0,0),List(0,1,0),List(0,0,1))
val empty:List[Nothing]=List()

//16.3 构建列表
val fruit="apple"::("banana"::("sealfruit"::"orange"))
val num=1::(2::(3::(5::4::Nil)))
val d3=(1::(0::(0::Nil)))::(0::(1::(0::Nil)))::(0::(0::(1::Nil)))
val empty=Nil
# 通过 :: add 不改变原List

//16.4列表的基本操作
head				返回列表第一个元素
tail				返回除第一元素外其他元素
isEmpty				判断是否为空

//example:插入 & 排序算法
def insert(x:Int,xs:List[Int]):List[Int]=if (xs.isEmpty || x<=xs.head) x::xs else xs.head :: insert(x,xs.tail)
def isort(xs:List[Int]): List[Int]=if (xs.isEmpty) Nil else insert(xs.head,isort(xs.tail))

-----------------------------------------------test------------------------------------------------
scala> insert(2,List(0,1,3))				--->res3: List[Int] = List(0, 1, 2, 3)
scala> isort(List(1,2,4,0,1))				--->res8: List[Int] = List(0, 1, 1, 2, 4)
---------------------------------------------------------------------------------------------------

//16.5 列表模式
val List(a,b,c,d)=fruit
a: String = apple
b: String = banana
c: String = sealfruit
d: String = orange
--->
val a :: c :: rest = fruit
a: String = apple
c: String = banana
rest: List[String] = List(sealfruit, orange)

//用模式匹配实现 插入 & 排序算法
def isort(xs:List[Int]): List[Int] = xs match{case List() => List();case x :: xs1 => insert(x,isort(xs1))}
def insert(x:Int,xs:List[Int]):List[Int]=xs match{case List()=>List();case y :: ys => if(x<=y) x :: xs else y::insert(x,ys)}


//16.6 List类的初阶方法
//16.6.1合并列表
List(1,2) ::: List(3,4,5)
List() ::: List(1,2,3)

//16.6.2分治原则
//实现append方法
def append[T](xs:List[T],ys:List[T]):List[T]=xs match {case List()=>ys;case x::xs1=>x::append(xs1,ys)}

//16.6.3获取列表长度 length
scala> List(1,2,3).length				--->res9: Int = 3

//16.6.4 访问列表的末端:init和last
#init(除尾元素) last(尾元素)
val asd=List("a","s","d","f","g")
scala> asd.last						--->res11: String = g
scala> asd.init						--->res12: List[String] = List(a, s, d, f)

//16.6.5 反转列表 reverse
scala> asd.reverse					--->res13: List[String] = List(g, f, d, s, a)
asd.reverse.tail
asd.reverse.init

//16.6.6前缀和后缀:drop,take和splitAt	*
asd splitAt <===> (asd take n ,asd drop n)
val a =List(1,2,3,4,5,6,7,8,9)
scala> a take 3						--->res19: List[Int] = List(1, 2, 3)
scala> a drop 2						--->res22: List[Int] = List(3, 4, 5, 6, 7, 8, 9)
scala> a splitAt 2					--->res25: (List[Int], List[Int]) = (List(1, 2),List(3, 4, 5, 6, 7, 8, 9))

//16.6.7 元素选择 apply和indices	*
scala> a apply 2					--->res1: Int = 3
a apply n  <===>  a(n)  <===>   (a drop n).head
scala> a.indices					--->res5: scala.collection.immutable.Range = Range 0 until 9

//16.6.8扁平化列表:flatten		*
List(List(1,2),List(3),List(4,5),List()).flatten	--->res8: List[Int] = List(1, 2, 3, 4, 5)
fruit.map(_.toCharArray).flatten			--->res9: List[Char] =List(a,p,p,l,e,b,a,n,a,n,a,s,e,a,l,f,r,u,i,t,o,r,a,n,g,e)

//16.6.9 将列表zip起来:zip和unzip
a.indices zip a
res16: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9))

scala> val zipped = a zip List(1,2,3)
zipped: List[(Int, Int)] = List((1,1), (2,2), (3,3))
//zip元素+位置标号
scala> a.zipWithIndex
res17: List[(Int, Int)] = List((1,0), (2,1), (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8))

scala> val c=List("a","b","c","d")			--->c: List[String] = List(a, b, c, d)
scala> c.zipWithIndex
res0: List[(String, Int)] = List((a,0), (b,1), (c,2), (d,3))

//unzip:任何元祖列表可通过unzip转换回List
scala> zipped.unzip					--->res3: (List[Int], List[Int]) = (List(1, 2, 3),List(1, 2, 3))

//16.6.10 toString和mkstring
val c=List("a","b","c","d")
c.toString			//返回标准字符串形式
//examples:
//mkString(start,seq,end)
scala> c.mkString("[",",","]")				--->res10: String = [a,b,c,d]
scala> c mkString " "					--->res11: String = a b c d
scala> c mkString "/"					--->res12: String = a/b/c/d
scala> a.mkString					--->res1: String = 123456789
scala> a mkString("List(",",",")")			--->res2: String = List(1,2,3,4,5,6,7,8,9)

//StringBuilder
val buf=new StringBuilder
scala> a addString(buf,"(",";",")")			--->res4: StringBuilder = (1;2;3;4;5;6;7;8;9)


//16.6.10 转换列表:iterator,toArray,copyToArray
scala> val arr = a.toArray				--->arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> arr.toList					--->res5: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

//copyToArray:将列表中元素依次复制到数组的指定位置
a copyToArray (arr,start)

//examples:
scala> val arr2=new Array[Int](10)
arr2: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
List(1,2,3) copyToArray (arr2,3)
scala> arr2
res7: Array[Int] = Array(0, 0, 0, 1, 2, 3, 0, 0, 0, 0)

//通过迭代器
scala> val it=a.iterator				--->it: Iterator[Int] = non-empty iterator
scala> it.next						--->res8: Int = 1
scala> it.next						--->res9: Int = 2


//example:归并排序 (merge sort)
//针对List的归并排序函数
def msort[T](less:(T,T)=>Boolean)(xs:List[T]):List[T]={
	def merge(xs:List[T],ys:List[T]):List[T]=(xs,ys) match{
		case(Nil, _) => ys
		case(_,Nil) => xs
		case(x :: xs1,y :: ys1)=>if (less(x,y)) x::merge(xs1,ys) else y::merge(xs,ys1)
	}
	val n=xs.length/2
	if (n==0) xs
	else {
		val(ys,zs)=xs splitAt n
		merge(msort(less)(ys),msort(less)(zs))
	}
}

--------------------------------------------------------------test----------------------------------------------------------
scala> msort((x:Int,y:Int)=>x<y)(List(5,7,1,3))			--->res15: List[Int] = List(1, 3, 5, 7)
val intSort=msort((x:Int,y:Int)=>x<y) _
val reverseIntSortmsort=msort((x:Int,y:Int)=>x>y) _
val mixed=List(2,25,6,2,2,5,1,467,323)
scala> intSort(mixed)						--->res0: List[Int] = List(1, 2, 2, 2, 5, 6, 25, 323, 467)
scala> reverseIntSortmsort(mixed)				--->res2: List[Int] = List(467, 323, 25, 6, 5, 2, 2, 2, 1)
----------------------------------------------------------------------------------------------------------------------------


//16.7 List 类的高级方法
//16.7.1 映射 :map,flatmap & foreach
scala> List(1,2,3).map(_ +1)					--->res3: List[Int] = List(2, 3, 4)

val words=List("its","a","raining","day")
scala> words.map(_.length)					--->res6: List[Int] = List(3, 1, 7, 3)
scala> words map(_.toList.reverse.mkString)			--->res7: List[String] = List(sti, a, gniniar, yad)

scala> words.map(_.toList)
res8: List[List[Char]] = List(List(i, t, s), List(a), List(r, a, i, n, i, n, g), List(d, a, y))

scala> words.flatMap(_.toList)
res10: List[Char] = List(i, t, s, a, r, a, i, n, i, n, g, d, a, y)
//创建一个1<=j<i<5 的对偶(i,j)
List.range(1,5) flatMap(i=>List.range(1,i) map(j=>(i,j)))
/另一种写法
for (i<-List.range(1,5);j <- List.range(1,i)) yield (i,j)


//foreach
var sum=0
List(1,2,3,4,5) foreach (sum += _)
sum=15

//过滤列表: filter,partition,find,takeWhile,dropWhile,span
//examples:
scala> List(1,2,3,4,5) filter (_ %2==0)				--->res17: List[Int] = List(2, 4)
words filter(_.length==3)					--->res18: List[String] = List(its, day)

//partition:返回true和false的列表
xs partition p  <===>   (xs filter p,xs filter (!p(_)))
List(1,2,3,4,5) partition(_ %2==0)				--->res19: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5))

//find:返回满足条件的第一个元素而非全部
scala> List(1,2,3,4,5) find (_ %2==0)				--->res20: Option[Int] = Some(2)
scala> List(1,2,3,4,5) find (_ <=0)				--->res21: Option[Int] = None

//takeWhile & dropWhile 
//takeWhile 返回连续满足条件的最长前缀
scala> List(1,2,3,-4,5) takeWhile ( _ >0)			--->res29: List[Int] = List(1, 2, 3)
words.dropWhile (_ startsWith "t")

//span:将takeWhile和dropWhile操作合一
//example:<===> (xs takeWhile p,xs dropWhile p)
scala> List(1,2,3,-4,5) span(_ >0)				--->res39: (List[Int], List[Int]) = (List(1, 2, 3),List(-4, 5))

//对列表的前提条件检查:forall和exists
def haszerorow(m:List[List[Int]])=m exists(row =>row forall(_ ==0))
scala> haszerorow(List(List(),List(1)))				--->res45: Boolean = true

//折叠列表: `/:` 和 `:\`
//实现sum
def sum(xs:List[Int]):Int=(0 /: xs) (_ + _)
//实现累乘
def product(xs:List[Int]):Int=(1 /: xs)(_ * _)		//初始值=1 compord

//左折叠
(z /: xs)(op)			//z:起始值	xs:列表	op:二元操作
(z /:List(a,b,c))(op)			<===>		op(op(op(z,a),b),c)

scala> (""/:words)(_+" "+_)					--->res53: String = " its a raining day"
scala> (words.head/:words.tail)(_+" "+_)			--->res55: String = its a raining day

//右折叠
(xs /: z)(op)			//z:起始值	xs:列表	op:二元操作
(List(a,b,c) :\ z)(op)		<===>		op(a,op(b,op(c,z)))

//example:使用左右折叠完成列表拼接(用右折叠比左折叠更高效)
def flattenLeft[T](xss: List[List[T]])=(List[T]() /: xss)(_ ::: _)
def flattenRight[T](xss: List[List[T]])=(xss :\ List[T]())(_ ::: _)


//例:用fold反转列表 P331
def reverseLeft[T](xs:List[T])=(`sartvalue` /: xs)(`operation`)
def reverseLeft[T](xs:List[T])=(List[T]() /: xs){(xs,y)=>y::ys}

//SparkRDD 中的 fold用法示例
foldLeft 详解:	https://blog.csdn.net/ZCF1002797280/article/details/51289575
scala> val a = (1 to 6).toList					--->res162: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> a.fold(1)((i,j)=>i*j)					--->res160: Int = 720



//列表排序:sortWith
xs sortWith before 
List(1,-3,4,2,6) sortWith (_ < _)
words sortWith (_.length > _.length)


//16.8 List对象的方法
//16.8.1 从元素创建列表: List.apply
scala> List.apply(1,2,3)				--->res65: List[Int] = List(1, 2, 3)
//16.8.2 创建数值区间: List.range (List.range(from,util) or List.range(start,end,step))
scala> List.range(1,9,3)				--->res66: List[Int] = List(1, 4, 7)
scala> List.range(9,1,-3)				--->res68: List[Int] = List(9, 6, 3)
//16.8.3 创建相同元素的列表: List.fill
//example: 创建5个"a"
scala> List.fill(5)("a")				--->res69: List[String] = List(a, a, a, a, a)
//example:2个3元素list fill("ok")
scala> List.fill(2,3)("ok")				--->res70: List[List[String]] = List(List(ok, ok, ok), List(ok, ok, ok))

//16.8.4 表格化一个函数: List.tabulate
scala> val square=List.tabulate(5)(n=>n*n)
square: List[Int] = List(0, 1, 4, 9, 16)

scala> val multi=List.tabulate(5,5)(_ * _)
multi: List[List[Int]] = List(List(0, 0, 0, 0, 0),List(0, 1, 2, 3, 4),List(0, 2, 4, 6, 8),List(0, 3, 6, 9, 12),List(0, 4, 8, 12, 16))

//16.8.5 拼接多个列表: List.concat
scala> List.concat(List("a","b","c"),List("d"))			--->res74: List[String] = List(a, b, c, d)
scala> List.concat(List(),List("a,b,c"))			--->res75: List[String] = List(a,b,c)


//16.9 同时处理多个列表
scala> (List(10,30),List(3,4,5)).zipped.map(_ * _)			--->res76: List[Int] = List(30, 120)
scala> (List("abc","de"),List(3,2)).zipped.forall(_.length== _)		--->res78: Boolean = true
scala> (List("abc","de"),List(3,4)).zipped.exists(_.length != _)	--->res79: Boolean = true


//16.10 理解scala的类型推断算法 P336



=============================================================Chapter 17 使用其他集合类
//17.1 序列
//17.1.1 列表
val color=List("red","yellow","blue")
scala> color.head					--->res81: String = red
scala> color.tail					--->res82: List[String] = List(yellow, blue)
//17.1.2 数组
scala> val five =new Array[Int](5)			--->five: Array[Int] = Array(0, 0, 0, 0, 0)
scala> val f =new Array[String](5)			--->f: Array[String] = Array(null, null, null, null, null)
scala> val oneTofive=Array(1,2,3,4,5)			--->onwTofive: Array[Int] = Array(1, 2, 3, 4, 5)
scala> oneTofive(1)					--->res84: Int = 2

//17.1.3 列表缓冲 (list buffer)
import scala.collection.mutable.ListBuffer
scala> val buf=new ListBuffer[Int]			--->buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer()
scala> buf +=1						--->res85: buf.type = ListBuffer(1)
scala> buf +=2						--->res86: buf.type = ListBuffer(1, 2)
scala> buf +=3						--->res87: buf.type = ListBuffer(1, 2, 3)
scala> 4+=:buf						--->res90: buf.type = ListBuffer(4, 1, 2, 3)
scala> buf.toList					--->res91: List[Int] = List(4, 1, 2, 3)

//17.1.4 数组缓冲 (Array Byffer)
import scala.collection.mutable.ArrayBuffer
val buf2=new ArrayBuffer[Int]()
scala> buf2 +=8						--->res92: buf2.type = ArrayBuffer(8)
scala> buf2 +=15					--->res93: buf2.type = ArrayBuffer(8, 15)
scala> buf2.length					--->res94: Int = 2

//17.1.5 字符串(通过 StringOPS)
//example:判断是否包含大写
def hasUpperCase(s:String) =s.exists(_.isUpper)
scala> hasUpperCase("Its a Sunday")			--->res97: Boolean = true
//exercise:判断是否包含大写并返回位置
def upcase(s:String):Unit={for ((i,j)<-s.toList.zipWithIndex) if(i.isUpper) println("the "+(j+1)+" positon is upCase"+": "+i)}
^-^

//17.2 集和映射
//example:predef中的默认映射和集定义
object predef{
	type Map[A,+B]=collection.immutable.Map[A,B]
	type Set[A]=collection.immutable.Set[A]
	type Map=collection.immutable.Map
	type Set=collection.immutable.Set
	//...
}

//引入可变包
import scala.collection.mutable
scala> val muSet=mutable.Set(1,2,3)			--->muSet: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

//17.2.1 使用集
val text="pu chi , pu chi ! ha ha . ak a ! , pu chi ! "
scala> val w=text.split("[ ,!.]+")			--->w:Array[String] = Array(pu, chi, pu, chi, ha, ha, ak, a, pu, chi)
scala> val words=mutable.Set.empty[String]		--->words: scala.collection.mutable.Set[String] = Set()
//example:去重
for (word<-w) words += word.toLowerCase

-------------------------------table17.1 常用的 集(Set)操作----------------------------------
val num=Set(1,2,3)					创建集合
num + 5							添加元素
num - 3							移除一个元素
num ++ List(5,6)					添加多个元素
num -- List(1,2)					移除多个操作
num & Set(1,3,5,7)					取2个集的交集
num.size						返回集大小
num.contains(3)						是否包含 3
import scala.collection.mutable				让可变集合易于访问
val words = mutable.Set.empty[String]			创建一个空的可变集合
words += "the"						添加元素
words -= "the"						移除元素
words ++=List("do","the","fuck")			添加多个元素
words --=List("do","re")				移除多个元素
words.clear						清空所有元素
---------------------------------------------------------------------------------------------

//17.2.2 使用映射 Map
val map = mutable.Map.empty[String,Int]
map("hello")=1
map("three")=2
scala> map			--->res106: scala.collection.mutable.Map[String,Int] = Map(three -> 2, hello -> 1)
scala> map("hello")		--->res107: Int = 1

//example:WorldCounts
def countWords(text:String)={
	val counts=scala.collection.mutable.Map.empty[String,Int]		//创建一个空Map[String,Int]
	for (rawword<-text.split("[ ,.!]+")){					//拆分words
		val word=rawword.toLowerCase					//小写
		val oldcount=if (counts.contains(word)) counts(word) else 0	//返回键值,不存在则返回0
		counts += (word->(oldcount + 1))				//添加元素,若存在则+1操作
	}
	counts
}

scala> countWords(text)
res116: scala.collection.mutable.Map[String,Int] = Map(chi -> 3, ha -> 2, a -> 1, ak -> 1, pu -> 3)


-------------------------------table17.2 常用的 映射(Map)操作----------------------------------
val num=Map("i"->1,"ii"->2)				创建映射
num + ("vi"->6)						添加单条
num - "ii"						移除单条
num ++ List("iii"->3,"v"->5)				添加多条
num -- List("i","ii")					移除多条
num.size						返回Map大小
num.contains("ii")					返回是否含有"ii"
num("ii")						返回键值
num.keys						返回所有键
num.keySet						Set(所有键)
num.values						返回所有值
num.isEmpty						判断是否为空						
import scala.collection.mutable				让可变集合易于访问
val words=mutable.Map.empty[String,Int]			创建一个可变映射(空的)
words += ("one" -> 1)					添加单条
words -= "one"						移除单条
words ++= List("one"->1,"two"->2,"three"->3)		添加多条
words --= List("one","two")				移除多条
----------------------------------------------------------------------------------------------

//17.2.3 默认的集和映射 P350

---------------------------------table-17.3 默认的不可变集实现---------------------------------
0							scala.collection.immutable.EmptySet
1							scala.collection.immutable.Set1
2							scala.collection.immutable.Set2
3							scala.collection.immutable.Set3
4							scala.collection.immutable.Set4
5+							scala.collection.immutable.HashSet
----------------------------------------------------------------------------------------------
#scala的scala.collection.immutable.Map() 键值对超过5对时,则会使用不可变的HashSet

--------------------------------table-17.4 默认的不可变映射实现--------------------------------
0							scala.collection.immutable.EmptyMap
1							scala.collection.immutable.Map1
2							scala.collection.immutable.Map2
3							scala.collection.immutable.Map3
4							scala.collection.immutable.Map4
5+							scala.collection.immutable.HashMap
----------------------------------------------------------------------------------------------


//17.2.4 排序好的集和映射 (SortedSet & SortedMap) TreeSet & TreeMap
import scala.collection.immutable.TreeSet
scala> val tes=TreeSet(-415,4,6,4,6,49,7,9,7,3,1,464,47674,9685)
tes: scala.collection.immutable.TreeSet[Int] = TreeSet(-415, 1, 3, 4, 6, 7, 9, 49, 464, 9685, 47674)

scala> val cs=TreeSet("f","u","c","k")
cs: scala.collection.immutable.TreeSet[String] = TreeSet(c, f, k, u)

//example:TreeMap
import scala.collection.immutable.TreeMap
scala> var tm=TreeMap(1->"japo",-88->"nani",77->"slek")
tm: scala.collection.immutable.TreeMap[Int,String] = Map(-88 -> nani, 1 -> japo, 77 -> slek)

scala> tm +=(22->"bitch")
scala> tm
res142: scala.collection.immutable.TreeMap[Int,String] = Map(-88 -> nani, 1 -> japo, 22 -> bitch, 77 -> slek)


//17.3 在可变和不可变集合类之间选择

//不可变集不支持 += 操作
val people = Set("zieox","gussi")
scala> people +="oop"			--->error	//因为不可变集不支持 +=

--->//val -> var
var people = Set("zieox","gussi")
scala> people +="oop"
scala> people
res1: scala.collection.immutable.Set[String] = Set(zieox, gussi, oop)


//17.4 初始化集合
import scala.collection.mutable
scala> mutable.Map(1->"japo",-88->"nani",77->"slek")
res1: scala.collection.mutable.Map[Int,String] = Map(77 -> slek, -88 -> nani, 1 -> japo)

val stuff = mutable.Set[Any](42)

val colors=List("blue","yellow","green")
import scala.collection.immutable.TreeSet
scala> val ts=TreeSet(colors)				--->error
//TreeSet 添加 list *
scala> val ts=TreeSet[String]()++colors
ts: scala.collection.immutable.TreeSet[String] = TreeSet(blue, green, yellow)


//17.4.1 转换成数组或列表
scala> ts.toList					--->res4: List[String] = List(blue, green, yellow)
scala> ts.toArray					--->res5: Array[String] = Array(blue, green, yellow)

//17.4.2 在可变和不可变集及映射间转换
import scala.collection.mutable
scala> ts
	--->res7: scala.collection.immutable.TreeSet[String] = TreeSet(blue, green, yellow)

scala> val mutaSet=mutable.Set.empty ++=ts
	--->mutaSet: scala.collection.mutable.Set[String] = Set(blue, green, yellow)

scala> val immutaSet=Set.empty ++ mutaSet
	--->immutaSet: scala.collection.immutable.Set[String] = Set(blue, green, yellow)
//Map
scala> val muta=mutable.Map("i"->1,"ii"->2)
	--->muta: scala.collection.mutable.Map[String,Int] = Map(ii -> 2, i -> 1)

scala> val immu=Map.empty ++ muta
	--->immu: scala.collection.immutable.Map[String,Int] = Map(ii -> 2, i -> 1)


//17.5 元祖 tuple
//example:longestWord
def longestWord(w:String)={
	val words=w.split("[ ,.!]+")
	var word=words(0)
	var idx=0
	for (i <- 1 until words.length) if (words(i).length>word.length){word=words(i);idx=i}
	(word,idx)
}
-----------------------------------------------------test---------------------------------------------------
scala> val lw = longestWord("im,good.hahaha!")				--->lw: (String, Int) = (hahaha,2)
scala> lw._1								--->res11: String = hahaha
scala> lw._2								--->res12: Int = 2
scala> val (word,idx)=lw					--->word: String = hahaha;	idx: Int = 2

------------------------------------------------------------------------------------------------------------



=============================================================Chapter 18 可变对象
//18.1 什么对象时可变的
//example: BankAccount
class BankAccount{
	private var bal:Int=0
	def balance:Int=bal
	def deposit(amount:Int)={require(amount>0);bal+=amount}
	def withdraw(amount:Int):Boolean= if (amount>bal) false else {bal-=amount;true}
	def showBalance()=println("The balance of the account is : "+balance)
}

scala> val acc=new BankAccount					--->acc: BankAccount = BankAccount@20df25f8
scala> acc deposit 100
scala> acc withdraw 80						--->res14: Boolean = true
scala> acc withdraw 80						--->res15: Boolean = false

//18.2 可被重新赋值的变量和属性
#在scala中,每一个非私 (not private) 有的var成员都隐式地定义了对应的getter和setter方法
#var x	getter:x		setter:x_=
//example:共有var是如何被展开成getter和setter方法的
class time {
	private[this] var h=12
	private[this] var m=0
	def hour:Int=h
	def hour_=(x:Int)={h=x}
	def minute:Int=m
	def minute_=(x:Int)={m=x}
}

===>
//example:直接定义getter和setter方法 (有关联字段)
class time {
	private[this] var h=12
	private[this] var m=0
	def hour:Int=h
	def hour_=(x:Int)={require(0<=x && x<24);h=x}
	def minute:Int=m
	def minute_=(x:Int)={require(0<=x && x<60);m=x}
}

//example:(定义没有关联字段的getter和setter方法)
class Thermometer{
	var cel:Float= _			// = _ 表示初始缺省值
	def fah = cel*9/5 +32
	def fah_=(f:Float)={cel=(f-32)*5/9}
	override def toString=fah+"F/"+cel+"C"
}

//var cel:Float 这样将会定义一个抽象变量 而不是 一个没有被初始化的变量

scala> th.cel=100					--->th.cel: Float = 100.0
scala> th						--->res20: Thermometer = 212.0F/100.0C


//18.3 案例分析:离散时间模拟 P368
//18.4 用于描述数字电路的语言P369-P384



=============================================================Chapter 19 类型参数化
//19.1 函数式队列
https://www.cnblogs.com/fxjwind/p/3338829.html
函数式队列是一种数据结构,它支持3种操作
head			头元素
tail			除头元素
enqueue			返回一个将给定元素加到队尾的新队列

import scala.collection.immutable.Queue //不可变Queue
scala> val q = Queue(1,2,3)
q: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3)
scala> q enqueue 4
res30: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3, 4)


//实现函数式队列
class SlowAppendQueue[T](elems:List[T]){
	def head=elems.head
	def tail=new SlowAppendQueue(elems.tail)
	def enqueue(x:T)=new SlowAppendQueue(elems::List(x))
}

class SlowHeadQueue[T](smele:List[T]){
	def head=smele.last
	def tail=new SlowHeadQueue(smele.init)
	def enqueue(x:T)=new SlowHeadQueue(x::smele)
}

//example: 基本的函数式队列 P387
class Queue[T](private val leading:List[T],private val trailing:List[T]){
	private def mirror=
		if (leading.isEmpty) new Queue(trailing.reverse,Nil) 
		else this
	def head=mirror.leading.head
	def tail={
		val q=mirror
		new Queue(q.leading.tail,q.trailing)
		}
	def enqueue(x:T)=new Queue(leading,x:trailing)
}


//19.2 信息隐藏
//19.2.1 私有构造方法和工厂方法 
//example:通过标记为private来隐藏主构造方法
class Queue[T] private(private val leading:List[T],private val trailing:List[T])
#其表示参数leading和trailing时Queue私有的,只能从类本身及其伴生对象访问

scala> new Queue(List(1,2),List(3))			---> Error

//添加一个辅助构造方法
def this(elems:T*)=this(elems.toList,Nil)

//example:伴生对象中的apply工厂方法
object Queue{def apply[T](xs:T*)=new Queue[T](xs.toList,Nil)}

//19.2.2 备选方法:私有类
//example:函数式队列的类型抽象
trait Queue[T] {def head:T;def tail:Queue[T];def enqueue(x:T):Queue[T]}
object Queue{
	def apply[T](xs:T*):Queue[T]=new QueueImpl[T](xs.toList,Nil)
	private class QueueImpl[T](private val leading:List[T],private val trailing:List[T]) extends Queue[T]{
		def mirror=if (leading.isEmpty) new QueueImpl(trailing.reverse,Nil) else this
		def head:T=mirror.leading.head
		def tail:QueueImpl[T]={val q=mirror;new QueueImpl(q.leading.tail,q.trailing)}
		def enqueue(x:T)=new QueueImpl(leading,x::trailing)
	}
}

//19.3 型变注解
scala> def dnCompile(q:Queue)={}				--->Error
//Queue是一个泛形特质
scala> def dnCompile(q:Queue[AnyRef])={}			--->dnCompile: (q: Queue[AnyRef])Unit

//修改类定义要求队列子类型是协变的
trait Queue[+T]{...}
//逆变
trait Queue[-T]{...}
#其中+和-为型变注解

//example:一个不变的Cell类
class Cell[T](init:T){
	private[this] var current=init
	def get=current
	def set(x:T)={current=x}
}

//19.3.1 型变和数组
//java数组
String a1 = {"abc"};
Object[] a2 = a1;
a2[0] = new Integer(17);
String s = a1[0];

//scala:asInstanceOf 类型转换
scala> val a1 = Array("abc")						--->a1: Array[String] = Array(abc)
scala> val a2: Array[Any] = a1						--->Error
scala> val a2:Array[Object]=a1.asInstanceOf[Array[Object]]		--->a2: Array[Object] = Array(abc)

//19.4 检查型变注解
class StrangeIntQueue extends Queue[Int] {override def enqueue(x:Int)={println(math.sqrt(x));super.enqueue(x)}}
abstract class Cat[-T,+U] {def meow[W-](volume:T-,listener:Cat[U+,T-]):Cat[Cat[U+,T-]-,U+]+}

//19.5 下界
//example:带有下界的类型参数
class Queue[+T](private val leading:List[T],private val trailing:List[T]){
	def enqueue[U>:T](x:U)=new Queue[U](leading,x::trailing) //...
}

/*
class creature{def s()=println("cr")}
class living extends creature{def s2()=println("living")}
class human extends living {def s3()=println("human")}
*/

//19.6 逆变
https://blog.csdn.net/luofazha2012/article/details/80342579
https://www.cnblogs.com/jacksu-tencent/p/4979666.html

trait OutPutChannel[-T]{def write(x:T)}

//exampel:函数参数型变
class Publication(val title:String)
class Book(title:String) extends Publication(title)
object Library{
	val books:Set[Book]=Set(new Book("programming in scala"),new Book("walden"))
	def printBookList(info:Book=>AnyRef)={for(book<-books) println(info(book))}
}

object Customer extends App{
	def getTitle(p:Publication):String=p.title
	Library.printBookList(getTitle)
}





//19.7 对象私有数据
//example:优化后的函数式队列
class Queue[+T] private(private[this] var leading:List[T],private[this] var trailing:List[T]){
	private def mirror()=
		if (leading.isEmpty){while (!trailing.isEmpty){leading=trailing.head::leading;trailing=trailing.tail}}
	def head:T={mirror();leading.head}
	def tail:Queue[T]={mirror();new Queue(leading.tail,trailing)}
	def enqueue[U>:T](x:U)=new Queue[U](leading,x::trailing)
}


//19.8 上界
//example:混入ordered特质的person类
class Person(val firstname:String,val lastname:String) extends Ordered[Person]{
	def compare(that:Person)={
		val lastnamecomparison=lastname.compareToIgnoreCase(that.lastname)
		if(lastnamecomparison != 0) lastnamecomparison
		else firstname.compareToIgnoreCase(that.firstname)
	}
	override def toString = firstname+" "+lastname
}


//example:带有上界的归并排序函数
#"T<:Ordered[T]" 这个语法表示 类型参数T有一个上界 为Ordered[T]
def orderedMergeSort[T<:Ordered[T]](xs:List[T]):List[T]={
	def merge(xs:List[T],ys:List[T]):List[T]=
		(xs,ys) match {
				case (Nil, _ ) =>ys
				case ( _ , Nil) =>xs
				case (x::xs1,y::ys1)=>if (x<y) x::merge(xs1,ys) else y::merge(xs,ys1)
				}	
	val n=xs.length/2
	if (n==0) xs 
	else{
		val (ys,zs)=xs splitAt n
		merge(orderedMergeSort(ys),orderedMergeSort(zs))
	}
}

val p=List(new Person("Larry","wall"),new Person("ader","voo"),new Person("jacci","wong"),new Person("asdf","qew"),new Person("ad","asd"))

scala> orderedMergeSort(p)
res43: List[Person] = List(ad asd, asdf qew, ader voo, Larry wall, jacci wong)

//exmple:
class Animal {}
class Bird extends Animal {}
class Consumer[-S,+T]() {
	def m1[U >: T](u: U): T = {new T} //协变,下界
	def m2[U <: S](s: S): U = {new U} //逆变,上界
	}
class Test extends App {
	val c:Consumer[Animal,Bird] = new Consumer[Animal,Bird]()
	val c2:Consumer[Bird,Animal] = c
	c2.m1(new Animal)
	c2.m2(new Bird)
}


=============================================================Chapter 20 抽象成员
//20.1 抽象成员概览
trait Abstract {
	type T				//使用type指定泛型的类型
	def transform (x:T):T
	val initial:T
	var current:T
}
//Abstract特制的抽象具体实现
class concrete extends Abstract{
	type T=String
	def transform (x:String)=x+x
	val initial="hi"
	var current=initial
}

//20.2 类型成员 :	type 关键字声明的某个类或特质成员

//20.3 抽象的val
//example: val-by-val,def-by-def 重写抽象val和无参方法
abstract class fruit{val v:String;def m:String}
abstract class apple extends fruit{val v:String;val m:String}

//20.4 抽象的var
trait abstractTime{var hour:Int;var minute:Int}
===>
trait abstractTime {
	def hour:Int
	def hour_=(x:Int)
	def minute:Int
	def minute_=(x:Int)
}

//20.5 初始抽象的val
#抽象val有时会承担超类参数的职能,他们允许我们在子类中提供那些在超类中缺失的细节。
//example:
trait rationalTrait{val numerArg:Int;val denomArg:Int}
--->实例化rationalTrait特质的具体实例
new rationalTrait{val numerArg=1;val denomArg=2}

new Rational(expr1,expr2)
#对于类而言,expr1和expr2会在Rational类初始化之前被求值,而对于特质则相反

new rationalTrait{val numArg=expr1;val denomArg=expr2}
#对于特质,expr1和expr2作为匿名类初始化过程的一部分被求值的,但是匿名类是在rationalTrait特质子后被初始化的

//example
scala> val x=2
scala> new RationalTrait{val numerArg=1*x;val denomArg=2*x}		--->error
#简单字面量之外的表达式作为分子分母来实例化这个特质,会得到这个异常

trait RationalTrait{
	val numerArg:Int
	val denomArg:Int
	require(denomArg !=0)
	private val g=gcd(numerArg,denomArg)
	val numer=numerArg/g
	val denom=denomArg/g
	private def gcd(a:Int,b:Int):Int= if(b==0) a else gcd(b,a%b)
	override def toString=numer+" / "+denom
}

#这个例子展示了 类参数在传入类构造方法之前被求值(传名参数除外),而在子类中实现的val定义则是在超类初始化之后被求值的。

--->预初始化字段(pre-initialized field)和惰性(lazy)的val
//20.5.1 预初始化字段
#在超类被调用之前初始化子类的字段
//example:匿名表达式中预初始化的字段
new {val numerArg=1*x;val denomArg=2*x} with RationalTrait		//使用匿名表达式初始化值

#预初始化字段不仅仅局限于匿名类,它们也可以被用在对象或具名子类中
//example:对象定义中的预初始化字段
object twoThird extends {val numerArg=2;val denomArg=3}with RationalTrait
//example:类定义中的预初始化字段
class RationalClass(n:Int,d:Int) extends{val numerArg=n;val denomArg=d} with RationalTrait{
	def + (that:RationalClass)=new RationalClass(numer*that.denom+that.numer*denom,denom*that.denom)
}

//20.5.2 惰性(lazy)的val P420
object Demo {val x={println("testing for initializing x");"done"}}
scala> Demo						--->testing for initializing x res84: Demo.type = Demo$@4340cb02
scala> Demo.x						--->res85: String = done


object demon {lazy val x={println("testing for initializing x");"done"}}
scala> demon						--->res86: demon.type = demon$@5d15231d
scala> demon.x						--->testing for initializing x	res87: String = done
#此刻demon的初始化不涉及x的初始化,对x的初始化延迟到第一次反问x的hi后

//example:初始化带惰性的val的特质
trait LazyRationalTrait{
	val numerArg:Int
	val denomArg:Int
	lazy val numer=numerArg/g
	lazy val denom=denomArg/g
	override def toString=numer+" / "+denom
	private lazy val g={require(denomArg !=0);gcd(numerArg,denomArg)}
	private def gcd(a:Int,b:Int):Int= if(b==0) a else gcd(b,a%b)
}

scala> val x=2
scala> new LazyRationalTrait{val numerArg=1*x;val denomArg=2*x}				--->res2: LazyRationalTrait = 1 / 2


//20.6 抽象类型
//example:
class food 
abstract class animal{def eat(food:food)}
class grass extends food 
class cow extends food 
class cow extends animal {override def eat(food:grass)}
--->
class food 
abstract class animal{
	type SuitableFood<:food
	def eat(food:SuitableFood)
}

//example:在子类中实现抽象类型
class grass extends food 
class cow extends animal {
	type SuitableFood=grass
	override def eat(food:grass)={}
}

class fish extends food 
val bss:Animal=new cow
scala> bss eat (new fish)						--->error
#参数类型不兼容

//20.7 路径依赖类型
class dogfood extends food
class dog extends animal{
	type SuitableFood=dogfood
	override def eat(food:dogfood)={}
}

val bessy=new cow
val lassie=new dog
scala> lassie eat (lassie.SuitableFood)					--->error
val boostie=new dog
lassie eat (new boostie.SuitableFood)					--->ok


//20.8 改良类型
#scala实现结构子类型的方式是改良类型
class Pasture{var animals:List[animal {type SuitableFood=grass}]=Nil/* ... */}

//20.9 枚举
import scala.Enumeration
object color extends Enumeration{val red,green,blue = Value}
//example:给枚举关联特定的值
object direction extends Enumeration{
	val north = Value("north")
	val east = Value("east")
	val west = Value("west")
	val south = Value("east")
}
//遍历枚举值
scala> for (d<-direction.values) print(d+" ")				--->north east west east
//通过枚举值ID返回编号
scala> direction.east.id						--->res8: Int = 1
scala> direction(2)							--->res11: direction.Value = west

//20.10 案例分析:货币
//example:创建一个名为CurrencyZone的工厂方法类
abstract class currencyzone{
	type currency<:AbstractCurrency
	def make(x:Long):currency
	abstract class AbstractCurrency{
		val amount:Long
		def designation:String
		override def toString=amount+" "+designation
		def + (that:currency):currency=make(this.amount+that.amount)
		def * (x:Double):currency=make((this.amount*x).toLong)
	}
	 val CurrencyUnit:currency		//创建货币单位
}

//example:创建US货币
object US extends currencyzone{
	abstract class Dollar extends AbstractCurrency{def designation="USD"}
	type currency=Dollar
	def make(x:Long)=new Dollar{val amount=x}
}

scala> val a = new US					--->a: US = US@57e0b2fa
scala> a.make(100)					--->res14: a.Dollar = 100 USD

--->美元货币区
object US extends currencyzone{
	abstract class Dollar extends AbstractCurrency{def designation="USD"}
	type currency=Dollar
	def make(cents:Long)=new Dollar{val amount=cents}
	val cent=make(1)
	val CurrencyUnit=Dollar
}

//Eurpo&Japan
object europe extends currencyzone{
	abstract class euro extends AbstractCurrency{def designation="EUR"}
	type curency =euro
	def make(cents:Long)=new euro{val amount=cents}
	val cent=make(1)
	val CurrencyUnit=euro
}
object japan extends currencyzone{
	abstract class yen extends AbstractCurrency{def designation="JPY"}
	type curency =yen
	def make(yen:Long)=new yen{val amount=yen}
	val cent=make(1)
	val CurrencyUnit=yen
}
//创建带有汇率映射的转换器对象
object Converter{
	var exchangeRate=Map(
		"USD"->Map("USD"->1.0,"Eur"->10.7569,"JPY"->1.211,"CHF"->1.223),
		"Eur"->Map("USD"->1.3,"Eur"->10.2333,"JPY"->1.594,"CHF"->1.623),
		"Jpy"->Map("USD"->0.8275,"Eur"->0.6272,"JPY"->1.0,"CHF"->1.018),
		"Chf"->Map("USD"->0.8108,"Eur"->0.6160,"JPY"->0.982,"CHF"->1.0)
		)
}

//最终版:currencyzone
abstract class currencyzone{
	type currency<:AbstractCurrency
	def make(x:Long):currency
	abstract class AbstractCurrency{
		val amount:Long
		def designation:String
		def + (that:currency):currency=make(this.amount+that.amount)
		def * (x:Double):currency=make((this.amount*x).toLong)
		def - (that:currency):currency=make(this.amount-that.amount)
		def / (that:currency)=this.amount.toDouble/that.amount
		def from(other:currencyzone#AbstractCurrency):currency=
			make(math.round(other.amount.toDouble*Converter.exchangeRate(other.designation)(this.designation)))
		private def decimals(n:Long):Int=if(n==1) 0 else 1 + decimals(n/10)
		override def toString=
			((amount.toDouble/CurrencyUnit.amount.toDouble)
				formatted("%."+decimals(CurrencyUnit.amount)+"f"+" "+designation))
	}
 	 val CurrencyUnit:currency
}



=============================================================Chapter 21 隐式函数和隐式参数
https://www.cnblogs.com/MOBIN/p/5351900.html
https://www.jianshu.com/p/4b1b5eaa6611
https://www.jianshu.com/p/1c6eb4cb641c
//21.1 隐式转换
import scala.language.implicitConversions 
#隐式转换可以减少从一个类型显示转换成另一个类型的需要
//example:非隐式转换的监听写法
val button = new JButton
button.addActionListener(new ActionListener{def actionPerformed(event:ActionEvent)={println("pressed !")}})

//example:编写隐式转换
implicit def f2ActionListener(f:ActionEvent=>Unit)=new ActionListener{def actionPerformed(event:ActionEvent)=f(event)}

#这个单参数方法返回一个函数并返回一个动作监听器
--->
button.addActionListener(f2ActionListener((_: ActionEvent)=>println("pressed!")))
--->
button.addActionListener((_: ActionEvent)=>println("pressed!"))

//21.2 隐式规则
#隐式定义是指那些我们允许编译器插入程序以解决错误类型的定义
#例如 x+y 不能通过编译,而convert(x)+y 可以,其中convert就是隐式转换

//21.2.1 标记规则
#只有标记为implicit的定义可用:	implicit def intToString(x:Int)=x.toString

//21.2.2 作用域规则:被插入的隐式转换必须是单个标识符,或和隐式转换的源类型或目标类型有关联 P446
//example:将隐式定义放在Dollar的伴生对象中
object Dollar{implicit def dollarToEuro(x:Dollar):euro= ... }
class Dollar{...}

//21.2.3 每一次规则:每次只能有一个隐式被插入
#不存在 convert1(convert2(x))+y
//21.2.4 显示优先原则:只要代码按照编写的样子能通过类型检查,就不会尝试隐式定义
//21.2.5 命名一个隐式转换
object MyConv{
	implicit def stringWrapper(s:String):IndexedSeq[Char]=...
	implicit def intToString(x:Int):String=...
}
//调用
import MyConv.stringWrapper

//21.2.6 在哪些地方会尝试隐式转换
	1. 转换到一个预期的类型
	2. 对某个选择接收端的转换
	3. 隐式转换


//21.3 隐式转换到一个预期的类型
import scala.language.implicitConversions 
//example:
scala> val i:Int=3.33					--->Error
scala> implicit def doubleToInt(x:Double)=x.toInt	//创建隐式转换
scala> val i:Int=3.33					--->i: Int = 3
scala> val i:Int=3.33					--->i: Int = 3
scala> val i:Int=doubleToInt(3.33)			--->i: Int = 3
scala> implicit def InToDouble(x:Int)=x.toDouble	--->InToDouble: (x: Int)Double
scala> val i:Double=InToDouble(3)			--->i: Double = 3.0


//21.4 转换接收端
#隐式转换还可应用于方法调用的接受端,也就是被调用的那个对象
//21.4.1 与新类型的互操作
//case:Rational
-----------------------------------------------------------------------------------------------------------------
class Rational (n:Int,d:Int){
	require(d != 0)
	private val g = gcd(n.abs,d.abs)
	val number = n / g
	val denom = d / g
	def this(n:Int) = this (n, 1)
	def + (that: Rational): Rational = new Rational(number*that.denom+denom*that.number,denom*that.denom)
	def - (that: Rational): Rational = new Rational(number*that.denom-denom*that.number,denom*that.denom)
	def - (i: Int): Rational = new Rational(number-i*denom,denom)
	def * (that: Rational): Rational=new Rational(number*that.number,denom*that.denom)
	def * (i: Int): Rational = new Rational(number*i,denom)
	def add(that: Rational) : Rational = new Rational(number*that.denom+that.number*denom,denom*that.denom)
	def / (that: Rational): Rational = new Rational(number*that.denom,denom*that.number)
	def / (i: Int): Rational = new Rational(number,denom*i)
	override def toString = number+"/"+denom
	private def gcd(a: Int,b: Int): Int = if (b==0) a else gcd(b,a%b)
}

-----------------------------------------------------------------------------------------------------------------
scala> val onehalf=new Rational(1,2)					--->onehalf: Rational = 1/2
scala> onehalf+onehalf							--->res17: Rational = 1/1
#when 
scala> onehalf+1							--->Error
#then
implicit def intToRational(x:Int)=new Rational(x,1)			//创建隐式转换
scala> onehalf+1							--->res19: Rational = 3/2
scala> intToRational(1)+onehalf						--->res19: Rational = 3/2
-----------------------------------------------------------------------------------------------------------------

//21.4.2 模拟新语法
Map("1"->"one","2"->"two","3"->"three")

//关于Map的"->",的富包装类模式
package scala 
object Predef {
	class ArrowAssoc[A] (x: A){def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y) }
	implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
}

//21.4.3 隐式类
case class Rectangle(width:Int,height:Int)
implicit class RectangleMaker(width:Int){def x(height:Int)=Rectangle(width,height)}

scala> val t=3 x 4							--->t: Rectangle = Rectangle(3,4)
scala> val t=RectangleMaker(3) x 4					--->t: Rectangle = Rectangle(3,4)


//21.5 隐式参数
class PreferredPrompt(val preference:String)
object Greeter {
	def greet(name:String)(implicit prompt:PreferredPrompt)={
		println("welcome, "+name+". The system is read.")
		println(prompt.preference)
	}
}

val bp=new PreferredPrompt("relax> ")
scala> Greeter.greet("bob")(bp)						--->welcome, bob. The system is read.;relax> 

//
object JoesPrefs{implicit val prompt=new PreferredPrompt("yes,master")}
//引入对象作用域
import JoesPrefs._
scala> Greeter.greet("MIK")						--->welcome, MIK. The system is read.
									    yes,master
//example: 带有多个参数的隐式参数列表
class PreferredPrompt(val preference:String)
class PreferredDrink(val preference:String)
object Greeter{
	def greet(name:String)(implicit prompt:PreferredPrompt,drink:PreferredDrink)={
		println("welcome, "+name+". The system is read.")
		print("but while you work")
		println("why not enjoy a cup of "+drink.preference+"?")
		println(prompt.preference)
	}
}
object JoesPrefs{
	implicit val prompt=new PreferredPrompt("yes,master") 
	implicit val drink=new PreferredDrink("tea")
}

Greeter.greet("Joe")							--->Error
//引入JoesPrefs作用域
import JoesPrefs._
Greeter.greet("Joe")							--->welcome, Joe. The system is read.
									    but while you workwhy not enjoy a cup of tea?
									    yes,master
//example:带有上界的函数
def maxListOrdering[T](elements:List[T])(ordering:Ordering[T]):T=
	elements match{
		case List()=>throw new IllegalArgumentException("empty list!")
		case List(x)=>x
		case x :: rest =>
			val maxRest=maxListOrdering(rest)(ordering)
			if(ordering.gt(x,maxRest)) x
			else maxRest
}

--->
def maxListImpParm[T](elements:List[T])(implicit ordering:Ordering[T]):T=
	elements match{
		case List()=>throw new IllegalArgumentException("empty list!")
		case List(x)=>x
		case x :: rest =>
			val maxRest=maxListImpParm(rest)(ordering)
			if(ordering.gt(x,maxRest)) x
			else maxRest
}

scala> maxListImpParm(List(1,2,5,3,22))				--->res9: Int = 22
scala> maxListImpParm(List(1,2,5,3.1,22))			--->res10: Double = 22.0

//隐式参数的代码风格规则 P459
def maxListPoorStyle[T](elements:List[T])(implicit order:(T,T)=>Boolean):T

//21.6 上下文界定
def maxList[T](elements:List[T])(implicit ordering:Ordering[T]):T=
	elements match{
		case List()=>throw new IllegalArgumentException("empty list!")
		case List(x)=>x
		case x :: rest =>
			val maxRest=maxList(rest)
			if (ordering.gt(x,maxRest)) x
			else maxRest
}

//使用implicitly的函数
def maxList[T](elements:List[T])(implicit ordering:Ordering[T]):T=
	elements match{
		case List()=>throw new IllegalArgumentException("empty list!")
		case List(x)=>x
		case x :: rest =>
			val maxRest=maxList(rest)
			if (implicitly[Ordering[T]].gt(x,maxRest)) x
			else maxRest
}

//带有上下文界定的函数
def maxList[T:Ordering](elements:List[T]):T=
	elements match{
		case List()=>throw new IllegalArgumentException("empty list!")
		case List(x)=>x
		case x :: rest =>
			val maxRest=maxList(rest)
			if (implicitly[Ordering[T]].gt(x,maxRest)) x
			else maxRest
}

//21.7 当有多个转换可用时
def printLength(seq:Seq[Int])=println(seq.length)
implicit def intToRange(i:Int)=1 to i
implicit def intToDigitals(i:Int)=i.toString.toList.map(_.toInt)


//21.8 调试
val chars:List[Char]=wrapString("xyz")

object Mocha extends App{
	class PreferredDrink(val preference:String)
	implicit val pref = new PreferredDrink("mocha")
	def enjoy(name:String)(implicit drink:PreferredDrink)={
		print("Welcome, "+name)
		print(". Enjoy a ")
		print(drink.preference)
		print("!")
	}
	enjoy("reader")
}

//Xprint:查看类型检查后添加乐隐式值的代码示例
$: scalac -Xprint:typer /home/lufax/桌面/scala/Mocha.scal



=============================================================Chapter 22 实现列表
http://blog.sina.com.cn/s/blog_9ca9623b0102waxj.html
//22.1 List类的原理
val xs =List(1,2,3)
var ys:List[Any]=xs::[T]-> List[+T] <-Nil

//22.1.1 Nil对象
//example:Nil单列对象的定义
case object Nil extends List[Nothing]{
	override def isEmpty=true
	def head:Nothing=throw new NoSuchElementException("head of empty list")
	def tail:List[Nothing]=throw new NoSuchElementException("tail od empty list")
}

//22.1.2 ::类 (cons)
final case class ::[T](hd:t,tl:List[T]) extends List[T]{
	def head = hd
	def talil=tl
	override def isEmpty:Boolean=false
}
//也可以等价于更加短小的::类定义:
final case class ::[T](head:T,tail:List[T]) extends List[T] {override def isEmpty:Boolean = false}

//22.1.3 更多方法
//list的其他方法都可以用这3个基本方法编写
def length:Int=if (isEmpty) 0 else 1+tail.length
or
def drop(n:Int):List[T]=
	if (isEmpty) Nil
	else if (n<=0) this 
	else tail.drop(n-1)
or
def map[U](f:T=>U):List[U]=if (isEmpty) Nil else f(head) :: tail.map(f)


//22.1.4 List的构造
scala> abstract class Fruit
scala> class Apple extends Fruit
scala> class Orange extends Fruit
scala> val apples = new Apple::Nil				-->apples: List[Apple] = List(Apple@aa4d8cc)
scala> val fruits = new Orange::apples				--->fruits: List[Fruit] = List(Orange@337bbfdf, Apple@aa4d8cc)

//List类中 :: (cons)的定义
def ::[U>:T](x:U):List[U]=new scala.::(x,this)
//List类中 ::: 的定义
def :::[U>:T](prefix:List[U]):List[U]=if (prefix.isEmpty) this else prefix.head::prefix.tail:::this
#like cons :::(拼接)方法是多态的

//22.2 ListBuffer类
def incAll(xs:List[Int]):List[Int]=xs match{
	case List()=>List()
	case x::xs1=>x+1 :: incAll(xs1)
}

import scala.collection.mutable.ListBuffer
val buf= new ListBuffer[Int]
for (x<-xs) buf += x+1
buf.toList


//22.3 List类的实践
#list类大多数方法的真实实现斌没有用递归,而是通过循环和列表缓冲
//example: List类中map方法的定义
final override def map[U](f:T=>U):List[U]={
	val b=new ListBuffer[U]
	var these=this
	while(!these.isEmpty){b+=f(these.head);these=these.tail}
	b.toList
}

//List子类中::方法的定义
final case class ::[U](hd:U,private[scala] var tl:List[U]) extends List[U]{
	def head=hd
	def tail=tl
	override def isEmpty:Boolean=false
}

import scala.collection.mutable
final class ListBuffer[T] extends Buffer[T] {
	private var start:List[T] = Nil
	private var last0: ::[T]= _
	private var exported: Boolean = false
	...
}

//example: +=
override def += (x:T) ={
	if (exported) copy()
	if (start.isEmpty){last0=new scala.::(x,Nil);start=last0}
	else {
		val last1=last0
		last0=new scala.::(x,Nil)
		last1.t1=last0	
		}
}

//22.4 外部可见的函数式 P479



=============================================================Chapter 23 重访for表达式
case class person(name:String,isMale:Boolean,children:person*)
val lara = person("lara",false)
val bob = person("bob",true)
val julia = person("julia",false ,lara,bob)
val persons = List(lara,bob,julia)
//筛选出childrens
persons filter(p => !p.isMale) flatMap (p=>(p.children map (c=>(p.name,c.name))))
//by: withFilter
persons withFilter (p => !p.isMale) flatMap (p=>(p.children map (c=>(p.name,c.name))))

//filter & withFilter
https://blog.csdn.net/feloxx/article/details/78307407
filter是将经过它的集合转换成一个新的集合
withFilter则是不生成新的集合

//by: for
for (p <- persons; if !p.isMale; c <- p.children) yield (p.name,c.name)

//23.1 for 表达式
// for (seq) yield expr: 查找以"j"开头的name
for (p<-persons;if(p.name startsWith "j")) yield p.name
//example:交叉排列
for (x<-List(1,2);y<-List("one","two")) yield (x,y)

//23.2 N皇后问题
def queen(n:Int):List[List[(Int,Int)]]={
	def placeQueens(k:Int):List[List[(Int,Int)]]=
		if (k==0) List(List())
		else{for {queens<-placeQueens(k-1);column <- 1 to n;queen=(k.column);if isSafe(queen,queens)} yield queen::queens}
		placeQueens(n)
	def isSafe(queen: (Int,Int),queens:List[(Int,Int)])=queens forall (q=> !inCheck(queen,q))
	def inCheck(q1:(Int,Int),q2:(Int,Int))=
		q1._1==q2._1	//同行
		q1._2==q2._2	//同列
		(q1._1-q2._1).abs==(q1._2-q2._2).abs	//斜线处
}


//23.3 用for推导式进行查询
case class Book(title:String,authors:String*)
val books:List[Book]=List(
		Book("Programming in java","Abelson hut","Susan wills"),
		Book("Python in Action","zieox zhang"),
		Book("Book of Fucking","Ullman","Jeffrey"),
		Book("how to die","lucias","wol"),
		Book("programming in scala","reed","butt"),
		Book("Scala jvm","butt")
		)
//23.3.1 翻译单个生成器的for表达式
for (x<-expr1) yield expr2
//same as
expr1.map(x=>expr2)
//23.3.2 翻译一个生成器和一个过滤器开始的for表达式
for (x<-expr1 if expr2) yield expr3
//same as 
for (x<-expr1 withFilter (x=>expr2)) yield expr3
//same as
expr1 withFilter (x=>expr2) map(x=>expr3)

for (x<-expr1 if expr2:seq) yield expr3
for (x<-expr1 withFilter expr2:seq) yield expr3

//23.3.2 翻译以2个生成器开始的for表达式
for (x<-expr1;y<-expr2;seq) yield expr3
expr1.flatMap(x=>for(y<-expr2;seq) yield expr3)
//选出至少编写>=2本书的作者
for (b1<-books;b2<-books if b1 != b2;a1<-b1.authors;a2<-b2.authors if a1==a2) yield a1
//same as 
books flatMap(b1=>books withFilter (b2=>b1 != b2) flatMap(b2=>b1.authors flatMap (a1=>b2.authors withFilter (a2=>a1==a2) map (a2=>a1))))

//23.3.3 翻译生成器中的模式
for ((x1,...,xn)<-expr1) yield expr2
//same as
expr1.map {case (x1,...,xn)=>expr2}

for (pat<-expr1) yield expr2
//same as 
expr1 withFilter{case pat=>true;case _ =>false} map{case pat =>expr2}

//23.3.4 翻译(for表达式中的)定义
for (x<-expr1;y=expr2;seq) yield expr3
//same as 
for ((x,y) <- for (x<-expr1) yield (x,expr2);seq) yield expr3
//
for (x<-1 to 1000;y=expensiveComputationNotInvolvingX) yield x*y
--->
val y=expensiveComputationNotInvolvingX
for (x<-1 to 1000) yield x*y


//23.3.5 翻译for循环
for (x<-expr1) body				<===>			expr1 foreach (x=>body)
for (x<-expr1;if expr2;y<-expr3) body		<===>			expr1 withFilter(x=>expr2) foreach (x=> expr3 foreach(y=>body))

//example
var sum=0
for (xs<-xss;x<-xs) sum+=x
--->
var sum=0
xss foreach(xs=> xs foreach (x=>sum+=))


//23.5 反过来
object demo {
	def map[A,B](xs:List[A],f:A=>B):List[B]=for(x<-xs) yield f(x)
	def flatMap[A,B](xs:List[A],f:A=>List[B]):List[B]=for(x<-xs;y<-f(x)) yield y
	def filter[A](xs:List[A],p:A=>Boolean):List[A]=for(x<-xs if p(x)) yield x
}

//23.6 泛化for表达式
abstract class C[A]{
	def map[B](f:A=>B):C[B]
	def flatMap[B](f:A=>C[B]):C[B]
	def withFilter(p:A=>Boolean):C[A]
	def foreach(b:A=>Unit):Unit
}



=============================================================Chapter 24 深入集合类
//24.1 可变和不可变集合 P499
//24.2 集合的一致性
import scala.collection.immutable._
Traversable(1,2,3)
Iterable("x","y","z")
Map("x"->23,"y"->"24","z"->25)
Set(Color.Red,Color.yellow,Color.green)
SortedSet("hello","kitty")
Buffer(x,y,z)
IndexedSeq(1.2,2.1)
LinearSeq(a,b,c)

//example:
scala> List(1,2,3) map (_+1)					--->res22: List[Int] = List(2, 3, 4)
scala> Set(2,3,4) map (_ *2)					--->res24: scala.collection.immutable.Set[Int] = Set(4, 6, 8)


//集合继承关系
-------------------------------------------------------------
Traversable
	Iterable
		Seq
			IndexedSeq
				Vector
				ResizableArray
				GenericArray
			LinearSeq
				MutableList
				List
				Stream
			Buffer
				ListBuffer
				ArrayBuffer
		Set
			SortedSet
				TreeSet
			HashSet
			LinkedHashSet
			HashSet
			BitSet
			EmptySet,Set1,Set2,Set3,Set4
		Map
			SortedMap
				TreeMap
			HashMap
			LinkedHashMap
			HashMap
			EmptyMap,Map1,Map2,Map3,Map4
-------------------------------------------------------------

//24.3 Traversable 特质
def foreach[U](f:Elem=>U)
1. 添加:		++
2. 映射操作:		map,flatMap,collect
3. 转换:		toIndexedSeq,toIterable,toStream,toArray,toList,toSeq,toSet,toMap
4. 拷贝:		copyToBuffer,copyToArray
5. 大小操作:		isEmpty,nonEmpty,size,hasDefiniteSize
6. 元素获取:		head,last,headOption,lastOption,find
7. 子集合获取操作:	takeWhile,tail,init,slice,take,drop,filter,dropWhile,filterNot,withFilter
8. 细分:		splitAt,span,partition,groupBy
9. 元素测试:		exists,forall,count
10.折叠:		foldLeft,foldRigth, /: , \: ,reduceLeft,reduceRight
11.特殊折叠:		sum,product,min,max
12.字符串操作:		mkString,addString,stringPrefix
13.视图操作:		

P505
https://blog.csdn.net/libing_thinking/article/details/41958059
-------------------------------------------table24.1 Traversable特质包含的操作-------------------------------------------
抽象方法:
	xs foreach f							对xs每个元素执行f函数
添加:
	xs++ys								包含xs和ys所有元素的集合
映射:
	xs map f							对xs每个元素映射f函数
	xs flatMap f							对xs每个元素应用f函数,并返回拼接结果
	xs collect f							对xs每个元素应用偏函数f并将有定义的结果收集起来得到集合
转换:
	xs.toArray							将集合转换成数组
	xs.toList							将集合转换成列表
	xs.toIterable							将集合转换成Iterable
	xs.toSeq							将集合转换成序列
	xs.toIndexedSeq							将集合转换成带下标的序列
	xs.toStream							将集合转换成流(一种惰性计算的序列)
	xs.toSet							将集合转换成集
	xs.toMap							将键值对转换成映射
拷贝:
	xs copyToBuffer buf						将集合的所有元素拷贝岛缓冲buf中
	xs copyToArray(arr,s,len)					将xs中最多len个元素拷贝到arr,从下标s开始,后两个入参可选
大小信息:
	xs.isEmpty							测试集合是否为空
	xs.nonEmpty							测试结合是否包含元素
	xs.size								集合中元素数量
	xs.hasDefiniteSize						如果xs的大小有限则返回
元素获取:
	xs.head								集合的首个元素
	xs.headOption							xs的首个元素,xs为空时返回None
	xs.last								集合最后一个元素
	xs.lastOption							集合最后一个元素,为空时返回None
	xs find p							xs中满足p的首个元素,当xs为空时返回None
子集合:
	xs.tail								除xs.head的部分
	xs.init								除xs.last的部分
	xs slice (from,to)						包含xs某个下标区间元素的集合([from,to) 其中不包含to)
	xs take n							取出n个元素
	xs drop n							除xs take n部分
	xs takeWhile p							从第一个元素开始遍历查找满足谓词条件 p 的元素,
									直到遇到一个不满足条件的元素,则返回所有目前找到的元素
	xs dropWhile p							其实就是xs 与 xs takeWhile p 的差集
	xs filter p							返回满足给定谓词条件 p 的所有元素组成的集合
	xs withFilter p							该集合的一个非严格的过滤器。后续对方法 map、flatMap 以及
									withFilter的调用都只针对xs中满足谓词条件 p 的元素,而忽略其他元素
	xs filterNot p							返回不满足给定谓词条件 p 的所有元素组成的集合
	
细分:	
	xs splitAt n 		在给定位置分裂集合,返回一个集合对 (xs take n, xs drop n)
	xs span p 		根据给定谓词集合分裂集合,返回一个集合对(xs takeWhile p, xs dropWhile p)
	xs partition p 		将 xs 分裂为两个集合;一个是由满足谓词条件 p 的元素组成的集合,另一个是不满足谓词条件 p 的元素组成的集合
	xs groupBy f 		根据给定的类别函数 f 将 xs 中的元素划分为不同的集合,最后返回一个映射,其中key为 f 产生的类别值,value 					为xs 中产生该类别值的所有元素组成的集合。
				a.groupBy((x:Int)=>x>50)(false)
元素条件:
	xs forall p							判断是否集合中所有的元素都满足谓词条件 p 
	xs exists p							判断是否集合中至少存在一个元素满足谓词条件 p
	xs count p							xs 中满足谓词条件 p 的元素的个数
折叠:
	(z /: xs) (op)							以 z 为初始值,从左到右对 xs 中的元素连续调用二元函数 op
	(xs :\ z) (op)							以 z 为初始值,从右到左对 xs 中的元素连续调用二元函数 op
	xs.foldLeft(z) (op)						同 (z /: xs) (op)
		(0/:(1 to 100))(_+_)				实现一个0~100的累加程序
		(1 to 100).foldLeft(0)(_+_)
		((1 to 5):\100)((i,sum)=> sum-i)		实现一个递减函数
	xs.foldRight(z) (op)						同 (xs :\ z) (op)
		def foldRight[B](z:B)(f(A,B) => B):B
		def foldLeft[B](z:B)(f(B,A) => B):B
	xs reduceLeft op 						 xs 中的元素连续调用二元函数 op
	xs reduceRight op						从右到左对非空集合 xs 中的元素连续调用二元函数 op
特殊折叠:
	xs.sum								xs 中所有元素的数值和
	xs.product							xs 中所有元素的数值积
	xs.min								xs 中所有元素中的最小值(元素需要是可比的)
	xs.max								xs 中所有元素中的最大值(元素需要是可比的)
字符串:
	xs addString (b, start, sep, end) 	向 StringBuilder 类的实例 b 中添加一个字符串,这个字符串显示了 xs 所有元素,具体格式以
						seq 字符串分隔元素,并将 start 字符串和 end
						字符串添加到头和尾。其中,start、seq 和 end都是可选的
	scala> List(1,2,3).addString(new StringBuilder,"<",",","--")		--->res9: StringBuilder = <1,2,3--
	scala> a.mkString("--",",",">")						--->res10: String = --1,2,3>

	xs mkString (start, seq, end)		将集合转化为一个字符串,这个字符串显示了 xs 所有元素,具体格式是以seq 字符串分隔元素,
						并将start 字符串和 end字符串添加到头和尾。其中,start、seq 和 end都是可选的
视图:
	xs.view					生成一个 xs 上的 view
	xs view (from, to)			生成一个view 来表示 xs 上指定索引范围内的元素 
---------------------------------------------------------------------------------------------------------------------------------
//用法示例:	http://www.cnblogs.com/weilunhui/p/5658860.html
//24.4 Iterable特质
def foreach[U](f:Elem=>U):Unit={
	val it=iterator
	while(it.hasNext) f(it.next())
}
//Sliding用法,grouped用法
val xs =List(1,2,3,4,5)
val git = xs grouped 3
scala> git.next()					--->res29: List[Int] = List(1, 2, 3)
scala> git.next()					--->res30: List[Int] = List(4, 5)
val sit = xs sliding 3
scala> sit.next()					--->res32: List[Int] = List(1, 2, 3)
scala> sit.next()					--->res33: List[Int] = List(2, 3, 4)
scala> sit.next()					--->res34: List[Int] = List(3, 4, 5)


----------------------------------------------------table24.2 Iterable 特质操作----------------------------------------------------
抽象方法
	xs.iterator						按照与foreach遍历元素的顺序交出xs中每个元素的迭代器
其他迭代器
	xs grouped size						交出集合固定大小的段迭代器
	xs sliding size						交出固定大小滑动窗口的元素的迭代器
子集合
	xs.takeRight n						取出右边n个元素
	xs.dropRight n						去除右边n个元素并返回
拉链
	xs zip ys						返回由xs和ys对应元素的对偶组成的Iterable
	xs zipAll (ys,x,y)					zip 短序列用x,y补足
	xs.zipWithIndex						返回xs中元素及下标的对偶组成的Iterable
比较
	xs sameElements ys					测试xs和ys是否包含顺序相同的元素
---------------------------------------------------------------------------------------------------------------------------------


//24.3.1 为什么要同时有Traversable和Iterable
sealed abstract class Tree
case class Branch(left:Tree,right:Tree) extends Tree
case class Node(elem:Int) extends Tree

sealed abstract class Tree extends Traversable[Int]{
	def foreach[U](f:Int=>U)=this match{
		case Node(elem)=>f(elem)
		case Branch(l,r)=>l foreach f;r foreach f
	}
}

sealed abstract class Tree extends Iterable[Int]{
	def iterator:Iterator[Int]=this match{
		case Node(elem)=>Iterator.single(elem)
		case Branch(l,r)=>l.iterator ++ r.iterator
	}
}

//24.3.2 Iterable的子类目(Seq,Set,Map) P511
//24.5 序列型特质Seq,IndexedSeq,LinearSeq
//24.5.1 下标和长度操作
apply,isDefinedAt,length,indices,lengthCompare
//24.5.2 下标检索操作
indexOf,lastIndexOf,indexOfSlice,lastIndexOfSlice,indexWhere,lastIndexWhere,segmentLength,prefixLength
//24.5.3 添加操作
+: , :+ 和padTO
//24.5.4 更新操作
updated,patch
//24.5.5 排序操作
sorted,sortWith,sortBy
//24.5.6 反转操作
reverse,reverseIterator,reverseMap
//24.5.7 多重操作
intersect,diff,union,distinct


----------------------------------------------------table24.3 Seq特质包含的操作----------------------------------------------------
下标和长度
	xs(i)								返回第i+1个元素
	xs isDefinedAt i						检查i是否包含于xs
	xs.length							返回序列长度
	xs.lengthCompare ys						比较长度 xs.length-ys.length
下标检索
	xs indexOf x							xs中首个x的元素下标
	xs lastIndexOf x						xs中最后一个x的元素下标
	xs indexOfSlice ys						xs中首个满足自该元素起的连续元素能构成ys序列的下标
	xs lastIndexOfSlice ys						xs中最后一个满足自该元素起的连续元素能构成ys序列的下标
	xs indexWhere p							xs中首个满足p的元素下标
	xs segmentLength(p,i)						xs中自xs(i)开始最长的连续满足p的片段长度
	xs prefixLength p						xs中最长的连续满足P的前缀长度
添加
	x +: xs								将x追加到xs头部
	xs :+ x								经x追加到xs尾部
	xs padTo (len,x)						将x追加到xs直到长度达到len
		scala> List(1,2) padTo (5,1)				--->res84: List[Int] = List(1, 2, 1, 1, 1)

更新
	xs patch (i,ys,r)						将xs中从下标i开始的r个元素替换成ys得到的序列
		val a = List(1,2)
		val b = List(3,4,5,6)					//b中第n+1 至 chosed 个元素由a代替
		b.patch(1,a,2)						--->res101: List[Int] = List(3, 1, 2, 5, 6)
	xs updated (i,x)						下标i的元素被替换成x的对xs的拷贝
		scala> List(1,2,3)updated(1,4)				--->res107: List[Int] = List(1, 4, 3)			
	xs(i)=x								更新下标为i的元素
排序
	xs.sorted							排序
	xs sortWith lessThan						以lessthan为比较操作对xs排序
	xs sortBy f							对xs元素排序后得到的新序列。两个元素间的比较通过同时应用f
	ex:https://blog.csdn.net/maybe_fly/article/details/77979867
		def testInt(): Unit ={var list = List(1,2,3,6,4,8,9,0);println(list.sortBy(sortIntRule))}
		List(1,2,3,6,4,8,9,0).sortBy(sortIntRule)
		def sortIntRule(i:Int) ={i match {case 1=> 2;case 2=> 1;case 3=> 4;case _=> 0}}

		class Person(age:Int,name:String,salary:Int) 
		{var AGE = age;var NAME = name;var SALARY = salary;override def toString = s"Person($AGE, $NAME, $SALARY)"}
		def TestSortBy(): Unit = {
			val personOne = new Person(18, "zhangsan", 10000)
			val personTwoA = new Person(20, "lisiA", 9000)
			val personTwoB = new Person(20, "lisiB", 10000)
			val personThree = new Person(15, "wangwu", 8000)
			var list = new ListBuffer[Person]
			list.+=(personOne, personTwoA,personTwoB, personThree)
			println(list.sortBy(sortRule)(Ordering.Tuple2(Ordering.Int.reverse, Ordering.Int.reverse)))}
		def sortRule(person: Person): (Int, Int) = {(person.AGE, person.SALARY)}

反转
	xs.reverse							反转顺序
	xs.reverseIterator						以颠倒的顺序交出xs所有元素的迭代器
	xs reverseMap f							以颠倒的顺序对xs的元素映射f返回
比较
	xs starstWith ys							测试xs是否以ys开始
	xs endsWith ys							测试xs是否以ys结束
	xs contains x							测试xs是否包含x
	xs containsSlice ys						测试xs是否包含与ys相等的连续子序列
	(xs corresponds ys)(p)						测试xs和ys对应元素是否满足二元前提条件p
多重操作
	xs intersect ys							xs与ys的交集,保持xs的顺序
	xs diff ys							xs与ys的差集,保持xs的顺序
	xs union ys							xs与ys的并集,等同于xs++ys
	xs.distinct							distnict
---------------------------------------------------------------------------------------------------------------------------------

//24.5.8 缓冲
----------------------------------------------------table24.4 Buffer特质包含的操作----------------------------------------------------
添加
	buf += x							将元素x追加岛缓冲buf中
	buf += (x,y,z)							添加元素
	buf ++= xs 							将xs中元素添加岛buf
	x +=: buf							将x向前追加到缓冲头部
	xs ++=: buf							将xs中所有元素向前追加到缓冲头部
	buf insert (i,x)						
	buf insertAll(i,xs)						
移除
	buf -= x							移除缓冲中的x
	buf remove i							移除缓冲中下标为i的元素
	buf remove (i,n)						移除缓冲从下标i开始的n个元素
	buf trimStart n							移除缓冲前n个元素
	buf trimEnd n							移除缓冲后n个元素
	buf.clear()							移除缓冲中所有元素
克隆
	buf.clone							跟buf拥有相同元素的新缓冲
	
------------------------------------------------------------------------------------------------------------------------------------

//24.6 集 Set
https://blog.csdn.net/high2011/article/details/52203446?utm_source=blogxgwz8
val f=Set("apple","orange","pinaple","banna","jerry")
scala> f("apple")						--->res48: Boolean = true

----------------------------------------------------table24.5 Set特质包含的操作----------------------------------------------------
测试
	xs contains x							测试xs中是否包含元素x	
	xs(x)								与 xs contains x 相同
	xs subsetOf ys							测试xs是否为ys的子集
添加
	xs + x								包含xs中所有元素以及x的集合。	 
	xs + (x, y, z)							包含xs中所有元素及附加元素的集合
	xs ++ ys							包含xs中所有元素及ys中所有元素的集合
移除
	xs - x								包含xs中除x以外的所有元素的集合。	 
	xs - x								包含xs中除去给定元素以外的所有元素的集合。	 
	xs – ys								集合内容为:xs中所有元素,去掉ys中所有元素后剩下的部分。	 
	xs.empty							与xs同类的空集合。
二元操作
	xs & ys								集合xs和ys的交集。
	xs intersect ys							等同于 xs & ys。
	xs|ys								集合xs和ys的并集。
	xs union ys							等同于xs|ys。
	xs &~ ys							集合xs和ys的差集。
	xs diff ys							等同于 xs &~ ys。
------------------------------------------------------------------------------------------------------------------------------------


----------------------------------------------------table24.6 mutable.Set特质包含的操作-----------------------------------------------------------------
加法
	xs += x							把元素x添加到集合xs中。该操作有副作用,它会返回左操作符,这里是xs自身。
	xs += (x, y, z)						添加指定的元素到集合xs中,并返回xs本身。(同样有副作用)
	xs ++= ys						添加集合ys中的所有元素到集合xs中,并返回xs本身。(表达式有副作用)
	xs add x						把元素x添加到集合xs中,如集合xs之前没有包含x,该操作返回true,否则返回false。
移除
	xs -= x							从集合xs中删除元素x,并返回xs本身。(表达式有副作用)
	xs -= (x, y, z)						从集合xs中删除指定的元素,并返回xs本身。(表达式有副作用)
	xs –= ys						从集合xs中删除所有属于集合ys的元素,并返回xs本身。(表达式有副作用)
	xs remove x						从集合xs中删除元素x。如之前xs中包含了x元素,返回true,否则返回false。
	xs retain p						只保留集合xs中满足条件p的元素。
	xs.clear()						删除集合xs中的所有元素。
更新
	xs(x) = b						( 同 xs.update(x, b) )参数b为布尔类型,如果值为true就把元素x加入集合xs,否则从集合xs中删除x。
克隆
	xs.clone						产生一个与xs具有相同元素的可变集合。
-----------------------------------------------------------------------------------------------------------------------------------------------------------
var s=Set(1,2,3)
scala> s+=4								--->error
var s=Set(1,2,3)
scala> s+=4								--->res65: s.type = Set(1, 2, 3, 4)


//24.7 映射
//24.7.1 查找
apply,get,getOrElse,contains,isDefinedAt
//24.7.2 添加和更新
+,++,update
//24.7.2 移除
-,--
//24.7.3 产生子集合
keys,keySet,keysIterator,valuesIterator,values
//24.7.4 变换
filterKeys,mapValues

----------------------------------------------------table24.7 Map 特质包含的操作--------------------------------------------------------------------
查找
	ms get k						根据键返回值
	ms(k)							(ms apply k)映射ms中跟键k关联的值,若无关则抛出异常
	ms getOrElse (k,d)					映射k关联的值,若无关联则返回d
	ms contains k						是否包含映射键K
	ms isDefinedAt k					同contains
添加和更新
	ms + (k->v)						添加映射关系
	ms +(k->v,l->w)						同上
	ms ++ kvs						map相加
	ms updated(k,v)						同 ms + (k->v)
移除
	ms - k							移除键与其对应的值
	ms - (k,l,m)						移除多个键与其对应的值
	ms -- ks						移除映射集
子集合
	ms.keys							返回ms中每个键的Iterable
	ms.keySet						返回ms中每个键的集
	ms.keysIterator						交出每个键的迭代器
	ms.values						返回映射中对应键的值
	ms.valuesIterator					返回映射中对应键的值的迭代器
变换
	ms filterKeys p						只包含ms中那些键满足前提条件p的映射关系的映射图
	ms mapValues f						通过对ms中每个跟键有关联的值应用函数f得到的映射视图
---------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------table24.8 mutable.Map 特质包含的操作-----------------------------------------------------------------
添加和更新
	ms(k) = v						以副作用将键k到值v的映射关系添加到映射ms,覆盖之前的k映射关系
	ms += (k->v)						添加映射关系
	ms += (k->v,l->w)					同上
	ms ++=kvs						++map
	ms put (k,v)						添加映射
	ms getOrElseUpdate(k,d)					如果k在ms中有定义则返回关联值,否则,用映射关系 k -> d 更新ms
移除
	ms -= k							移除映射键k及其值
	ms -= (k,l,m)						移除k,l,m
	ms --= ks						移除map
	ms remove k						从ms移除键k的映射关系并以可选值的形式返回键之前的关联值
	ms retain p						仅保留满足条件p的映射关系
	ms.clear()						清空ms
变换和克隆
	ms transform f						用函数f变换ms中所有关联值
	ms.clone						返回跟ms包含相同映射关系的新的可变映射
-----------------------------------------------------------------------------------------------------------------------------------------------------------
//example:P525
def f(x:String)={println("taking my time.");Thread.sleep(100);x.reverse}
val cache =collection.mutable.Map[String,String]()
def cachedF(s:String)=cache.getOrElseUpdate(s,f(s))
def cachedF(arg:String)=cache get arg match{
	case Some(result)=>result
	case None=>
		val result=f(arg)
		cache(arg)=result
		result
}


//24.8 具体的不可变集合类
//24.8.1 列表
//24.8.2 流
scala> var str=1 #:: 2 #:: 3 #:: Stream.empty						--->str: scala.collection.immutable.Stream[Int] = Stream(1, ?)
//fb 数列
def fib(a:Int,b:Int):Stream[Int]=a #:: fib(b,a+b)
scala> fibs										--->res19: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> fibs.toList									--->res20: List[Int] = List(1, 1, 2, 3, 5, 8, 13)

//24.8.3 向量
val vec=scala.collection.immutable.Vector.empty
scala> vec2										--->res22: scala.collection.immutable.Vector[Int] = Vector(1, 2)
scala> val vec3=100 +: vec2								--->vec3: scala.collection.immutable.Vector[Int] = Vector(100, 1, 2)
scala> vec3(1)										--->res23: Int = 1
#向量的内部结构是宽而浅的树,树的每个节点包含多达32个元素或32个其他数节点

scala> val vec = Vector(1,2,3)
vec: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> vec
res24: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> vec updated(2,4)
res25: scala.collection.immutable.Vector[Int] = Vector(1, 2, 4)

scala> collection.immutable.IndexedSeq(1,2,3)
res28: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)

//24.8.4 不可变栈 (栈:后进先出)
val stack=scala.collection.immutable.Stack.empty
#push压入,pop弹出,top查看栈顶元素不弹出
scala> val hasOne=stack.push(1)
hasOne: scala.collection.immutable.Stack[Int] = Stack(1)

scala> stack
res29: scala.collection.immutable.Stack[Nothing] = Stack()

scala> hasOne.top
res30: Int = 1

scala> hasOne.pop
res31: scala.collection.immutable.Stack[Int] = Stack()

//28.4.5 不可变队列 (队列:先进先出)
val empty = scala.collection.immutable.Queue[Int]()
//追加一个元素
scala> val h1=empty.enqueue(1)
h1: scala.collection.immutable.Queue[Int] = Queue(1)
//追加多个元素
scala> val h1=empty.enqueue(List(2,3))
h1: scala.collection.immutable.Queue[Int] = Queue(2, 3)
//从列表头部移除元素dequeue
scala> val has2=h1.enqueue(List(2,3))
has2: scala.collection.immutable.Queue[Int] = Queue(2, 3, 2, 3)
//从列表头部移除元素
scala> val (element,has23)=has2.dequeue
element: Int = 2
has23: scala.collection.immutable.Queue[Int] = Queue(3, 2, 3)

//24.4 区间
1 to 3			i c [1,2,3]
1 to 10 by 3		i c [1,4,7,10]
1 until 3		i c [1,2]

//24.5 哈希字典树 P530
//24.6红黑树
val set=collection.immutable.TreeSet.empty[Int]
scala> set + 1+2+3								--->res40: scala.collection.immutable.TreeSet[Int] = TreeSet(1, 2, 3)
#红黑树也是scala中SortedSet的标准实现

//24.7 不可变位组(bit set)P31
val bits=scala.collection.immutable.BitSet.empty
scala> moreBits									--->res42: scala.collection.immutable.BitSet = BitSet(3, 4)

//24.8 列表映射
scala> val map=collection.immutable.ListMap(1->"one",2->"two")
map: scala.collection.immutable.ListMap[Int,String] = ListMap(1 -> one, 2 -> two)
scala> map(2)									--->res43: String = two


//24.9 具体的可变集合类
//24.9.1 数组缓冲
val buf = collection.mutable.ArrayBuffer.empty[Int]
scala> buf +=1									--->res44: buf.type = ArrayBuffer(1)
scala> buf +=10									--->res46: buf.type = ArrayBuffer(1, 10)
scala> buf.toArray								--->res47: Array[Int] = Array(1, 10)

//24.9.2 列表缓冲
val buf = collection.mutable.ListBuffer.empty[Int]
scala> buf +=1									--->res52: buf.type = ListBuffer(1)
scala> buf +=10									--->res53: buf.type = ListBuffer(1, 10)
scala> buf.toList								--->res2: List[Int] = List(1, 10)

//24.9.3 字符串构建器
val buf = new StringBuilder
scala> buf += 'a'								--->res5: buf.type = a
scala> buf ++= "abcdef"								--->res6: buf.type = aabcdef
scala> buf.toString								--->res8: String = aabcdef

//24.9.4 链表 P534
//24.9.5 双向链表 DoubleLinkedList
//24.9.6 可变列表 MutableList
#MutableList 目前是scala的mutable.LinearSeq

//24.9.7 可变队列
val queue=new scala.collection.mutable.Queue[String]
scala> queue+="a"								--->res9: queue.type = Queue(a)
scala> queue++=List("b","c")							--->res10: queue.type = Queue(a, b, c)
scala> queue.dequeue								--->res12: String = a
scala> queue									--->res13: scala.collection.mutable.Queue[String] = Queue(b, c)

//24.9.8 数组序列 Array[AnyRef]
//24.9.9 可变栈
val stack=new scala.collection.mutable.Stack[Int]
scala> stack.push(1)								--->res14: stack.type = Stack(1)
scala> stack.push(1)								--->res14: stack.type = Stack(1)
scala> stack									--->res15: scala.collection.mutable.Stack[Int] = Stack(1)
scala> stack.push(2)								--->res16: stack.type = Stack(2, 1)
scala> stack.pop								--->res18: Int = 2
scala> stack									--->res19: scala.collection.mutable.Stack[Int] = Stack(1)

//24.9.10 数组栈 ArrayStack
//24.9.11 哈希表Hashtable
val map=collection.mutable.HashMap.empty[Int,String]
scala> map += (1->"make a web site")						--->res20: map.type = Map(1 -> make a web site)
scala> map +=(3->"profit!")							--->res21: map.type = Map(1 -> make a web site, 3 -> profit!)
scala> map(1)									--->res22: String = make a web site
scala> map contains 3								--->res24: Boolean = true

//24.9.12 弱哈希映射 WeakHashMap P538
//24.9.13 并发映射 p538 
----------------------------------------------------table24.9 ConcurrentMap 特质包含的操作-----------------------------------------------------
m putIfAbsent (k,v)								除非k已经在m中定义,添加k->v的键/值绑定
m remove (k,v)									如果k当前映射到v,移除该项目
m replace (k,old,new)								如果键k原先就绑定到old,将k关联的值替换为new
m replace (k,v)									如果键k原先绑定到某个值,将k关联的值替换为v

-----------------------------------------------------------------------------------------------------------------------------------------------

//24.9.14 可变位组
val bits=scala.collection.mutable.BitSet.empty
bits+=1
bits+=3


//24.10  数组 P539
val a1 = Array(1,2,3)
scala> val a1 = Array(1,2,3)							--->a1: Array[Int] = Array(1, 2, 3)
scala> val a2 = a1 map (_*3)							--->a2: Array[Int] = Array(3, 6, 9)
scala> val a3 = a2 filter (_%2 !=0)						--->a3: Array[Int] = Array(3, 9)

scala> val seq:Seq[Int]=a1							--->seq: Seq[Int] = WrappedArray(1, 2, 3)
scala> seq.reverse								--->res30: Seq[Int] = WrappedArray(3, 2, 1)
scala> val a4:Array[Int]=seq.toArray						--->a4: Array[Int] = Array(1, 2, 3)
scala> a1 eq a4									--->res31: Boolean = true

val ops:collection.mutable.ArrayOps[Int]=a1

//P543
import scala.reflect.ClassTag
def evenElems[T:ClassTag](xs:Vector[T]):Array[T]={
	var arr=new Array[T]((xs.length+1)/2)
	for (i<- 0 until xs.length by 2) arr(i/2)=xs(i)
	arr
}

scala> evenElems(Vector(1,2,3,4,5))						--->res32: Array[Int] = Array(1, 3, 5)
scala> evenElems(Vector("this","is","a","test","run","."))			--->res33: Array[String] = Array(this, a, run)
//
def wrap[U:ClassTag](xs:Vector[U])=eventElems(xs)


//24.11 字符串
scala> val str = "hello"							--->str: String = hello
scala> str.reverse								--->res34: String = olleh
scala> str.map(_.toUpper)							--->res35: String = HELLO
scala> str drop 3								--->res36: String = lo
scala> str slice (1,4)								--->res37: String = ell
scala> val s:Seq[Char]=str.toList						--->s: Seq[Char] = List(h, e, l, l, o)
//24.12 性能特征 P545

//24.13 相等性
import collection.mutable.{HashMap,ArrayBuffer}
import collection.mutable.{HashSet,TreeSet}
scala> List(1,2,3)==Vector(1,2,3)						--->res0: Boolean = true
scala> HashSet(1,2)==TreeSet(2,1)						--->res4: Boolean = true
scala> val buf = ArrayBuffer(1,2,3)
	--->buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
scala> val map = HashMap(buf->3)
	--->map: scala.collection.mutable.HashMap[scala.collection.mutable.ArrayBuffer[Int],Int] = Map(ArrayBuffer(1, 2, 3) -> 3)
scala> map(buf)									--->res5: Int = 3
scala> buf(0)+=1
scala> buf
	--->res8: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 2, 3)

//24.14 视图
//24.14.1 变换器(transformer): map,filter,++
def lazyMap[T,U](coll:Iterable[T],f:T=>U)=new Iterable[U]{def iterator=coll.iterator map f}

def lazyMap[T,U](coll:Iterable[T],f:T=>U)=new Iterable[U]{def iterator=coll.iterator map f}

//example:
scala> val v = Vector(1 to 10: _*)
	--->v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> v map (_ +1) map (_ *2)
	--->res12: scala.collection.immutable.Vector[Int] = Vector(4, 6, 8, 10, 12, 14, 16, 18, 20, 22)
//使用视图
scala> (v.view map (_ + 1) map (_ *2)).force
	--->res13: Seq[Int] = Vector(4, 6, 8, 10, 12, 14, 16, 18, 20, 22)
scala> val vv=v.view
	--->vv: scala.collection.SeqView[Int,scala.collection.immutable.Vector[Int]] = SeqView(...)
scala> vv map(_ + 1)
	--->res14: scala.collection.SeqView[Int,Seq[_]] = SeqViewM(...)
scala> res14 map (_ *2)
	--->res16: scala.collection.SeqView[Int,Seq[_]] = SeqViewMM(...)
scala> res16.force
	--->res17: Seq[Int] = Vector(4, 6, 8, 10, 12, 14, 16, 18, 20, 22)
#考虑使用视图的两个原因,1. 性能 2. 针对可变序列

//example:性能
def isPalindrome(x:String)= x==x.reverse
def findPalindrome(s:Seq[String])= s find isPalindrome
findPalindrome(words take 1000000)		//构造100万个元素的序列
--->
findPalindrome(words.view take 1000000)		//构造轻量级视图

//example:针对可变序列
scala> val arr = (0 to 9).toSet
	--->arr: scala.collection.immutable.Set[Int] = Set(0, 5, 1, 6, 9, 2, 7, 3, 8, 4)
scala> val subarr = arr.view.slice(3,6)
	--->subarr: scala.collection.mutable.IndexedSeqView[Int,Array[Int]] = SeqViewS(...)
scala> def negate(xs:collection.mutable.Seq[Int])=for (i<-0 until xs.length) {xs(i) = -xs(i)}
scala> negate(subarr)
scala> arr						--->res22: Array[Int] = Array(0, 1, 2, -3, -4, -5, 6, 7, 8, 9)
#subarr是arr的切片,negate修改了subarr所有元素,视图帮助我们保持模块化
scala> val actor=(1 to 10) map (i=>println("10 times"))
scala> val actor = for (i<- (1 to 10).view) yield println("10 times")
scala> actor.force
10 times
10 times
10 times
10 times
10 times
10 times
10 times
10 times
10 times
10 times
res23: Seq[Unit] = Vector((), (), (), (), (), (), (), (), (), ())


//24.15 迭代器:逐个访问集合元素的一种方式(it.next,it.hasNext)
while(it.hasNext) println(it.next())				//遍历
it foreach println
for(elem<-it)println(elem)
#迭代器foreach和可遍历集合(Traversable) 的同名方法有一个重要的区别:
#对迭代器执行foreach它执行之后将迭代器留在末端,而对集合调用foreach 它保持集合中的元素数量不变。

//example:迭代器
scala> val it = Iterator("a","number","of","words")			--->it: Iterator[String] = non-empty iterator
scala> it.map(_.length)							--->res32: Iterator[Int] = non-empty iterator
scala> res32 foreach println
1
6
2
5
scala> it.next								--->error
#it被调用后,it迭代器被推进到了末端

//example:dropWhile
scala> val it = Iterator("a","number","of","words")			--->it: Iterator[String] = non-empty iterator
scala> it dropWhile (_.length<2)					--->res43: Iterator[String] = non-empty iterator
scala> it.next()							--->res48: String = of
//重用迭代器
val (it1,it2)=it.duplicate

//Scala Iterator 常用方法:	http://www.runoob.com/scala/scala-iterators.html
---------------------------------------------------------table24.12 Iterator 特质包含的操作-------------------------------------------------------------
抽象方法
	it.next()									返回迭代器中下个元素并推进it到下一步
	it.hasNext									返回Boolean
变种
	it.buffered									返回it所有元素的带缓冲的迭代器
	it grouped size									以固定大小‘段’交出it的元素的迭代器
	it sliding size									以固定大小的滑动窗口交出it的元素的迭代器
拷贝
	it copyToBuffer buf								将it返回的所有元素拷贝到缓冲buf
	it copyToArray(arr,s,1)								将it返回的最多1个元素拷贝到数组arr,从下标s开始,后2个入参可选
复制
	it.duplicate									一对迭代,=每个都独立地返回it的所有元素
添加
	it ++ jt									返回it+jt所有元素的迭代器
	it padTo (len,x)								返回it所有元素以及x的拷贝直到返回元素的总长度达到len
映射
	it map f									对it每个元素应用f
	it flatMap f									对it每个元素应用f,并追加结果得到的迭代器
	it collect f									通过it返回的每个元素应用偏函数,并将有定义的结果收集起来得到的迭代器
转换
	it.toArray									转为数组
	it.toList									转为列表
	it.toIterable									转为Iterable
	it.toSeq									转为序列
	it.toIndexSeq									转为带下标的序列
	it.toStream									转为流
	it.toSet									转为集
	it.toMap									转为映射
大小信息
	it.isEmpty									测试迭代器是否为空
	it.nonEmpty									测试集合是否包含元素
	it.size										返回元素数量
	it.length									同it.szie
	it.hasDefiniteSize								如果已知将返回有限多的元素则返回true
元素获取和下标检索
	it find p									返回首个满足p的元素,若无None
	it indexOf x									返回首个x元素的下标
	it indexWhere p									it中首个满足p的元素下标
子迭代器
	it take n									返回it的头n个元素的迭代器
	it drop n									返回从it的第n+1个元素开始的迭代器
	it slice (m,n)									返回从it的第m个元素开始到第n个元素之前为止的元素的迭代器
	it takeWhile p									返回it中所有满足条件p的元素的迭代器
	it dropWhile p									返回跳过满足条件p的元素的迭代器
	it filter p									返回跳过it中所有满足条件p的元素的迭代器
	it withFilter p									同 it filter p 。为了支持for表达式语法
	it filterNot p									返回it中所有不满足条件p的元素的迭代器
细分
	it partition p									将it切分为2个迭代器: 其中一个返回it中所有满足条件p的元素,另一个为非
元素条件
	it forall p									是否it中所有元素都满足前提条件p的布尔值
	it exists p									是否it中有元素满足前提条件p的布尔值
	it count p									it中满足前提条件p的元素数量
折叠
	(z /: it)(op)									以z开始自左向右依次对it中连续元素应用二元操作op
	(it :\ z)(op)									以z开始自右向左依次对it中连续元素应用二元操作op
	it.foldLeft(z)(op)								同(z /: it)(op)
	it.foldRight(z)(op)								同(it :\ z)(op)
	it reduceLeft op								自左向右依次对非空迭代器it的连续元素应用二元操作op
	it reduceRight op								自右向左依次对非空迭代器it的连续元素应用二元操作op
特殊折叠
	it.sum										求和
	it.product									求积
	it.min										最小值
	it.max										最大值
拉链
	it zip jt									生成一个it与jt的对偶迭代
	it zipAll (jt,x,y)								生成对偶迭代器,其中较短序列用x或y的元素值延展成相同长度
	it zipWithIndex									由it中的元素及其下标的对偶组成的迭代器
更新
	it patch (i,jt,r)								将it中从位置i开始的r个元素替换成jt的元素得到迭代器
比较
	it sameElement jt								测试是否it和jt包含相同顺序的相同元素
字符串
	it addString (b,start,sep,end)							将一个显示乐it所有元素的字符串添加到StringBuilder b中,元素以sep分隔并包含在start和end当中。start,seq和end均为可选
	it mkString (start,seq,end)							将迭代器转换成一个显示乐it所有元素的字符串,元素以sep分隔并包含在start和end当中。start,seq和end均为可选
--------------------------------------------------------------------------------------------------------------------------------------------------------

//带缓冲的迭代器 BufferedIterator
def skipEmptyWordsNOT(it:Iterator[String])={while(it.next().isEmpty){}}
def skipEmptyWords(it:BufferedIterator[String])=while (it.head.isEmpty){it.next()}

//example:
val it = Iterator(1,2,3,4)
val bit = it.buffered
scala> bit.head										--->res84: Int = 1
scala> bit.next()									--->res85: Int = 1
scala> bit.next()									--->res86: Int = 2


//24.16 从头创建集合
Traversable()			//一个空的可便利对象
List()				//空列表
List(1,2,3,4)			//带有元素1,2,3,4的列表
Vector(1,2)			//带有元素1,2的向量
Iterator(1,2,3)			//带有3个整数的迭代器
Set(dog,cat,lion)		//由三个动物组成的集
HashSet(dog,cat,lion)		//由三个动物组成的哈希集
Map("a"->7,"b"->0)		//从字符串到整数的映射


-----------------------------------------------------------table24.13 序列的工厂方法--------------------------------------------------------------
s.empty										空的序列
s(x,y,z)									由 x,y,z 组成的序列
s.concat(xs,ys,zs)								拼接 xs,ys,zs
s.fill(n)(e)									长度为n的序列,其中每个元素由表达式e计算
s.fill(m,n)(e)									大小为m x n序列的序列,其中每个元素由表达式e计算
s.tabulate(n)(f)								产度为n的序列,其中下标i对应元素由f(i)计算得出
s.tabulate(m,n)(f)								大小为m x n序列的序列,其中每组下标(i,j)的元素由f(i,j)计算得出
s.range(start,end)								整数序列 start ... end -1
s.range(start,end,step)								从start开始,以step为步长,直到end值为止的整数序列
s.iterate(x,n)(f)								长度为n的序列,元素值为 x,f(x),f(f(x))...
-------------------------------------------------------------------------------------------------------------------------------------------------


//24.17 Java和Scala集合互转 P563
Iterator			java.util.Iterator
Iterator			java.util.Enumeration
Iterable			java.lang.Iterable
Iterable			java.util.Collection
mutable.Buffer			java.util.List
mutable.Set			java.util.Set
mutable.Map			java.util.Map

import collection.JaveConversions._
import collection.mutable._
val jul:java.util.List[Int]=ArrayBuffer(1,2,3)


=============================================================Chapter 25 Scala集合
https://docs.scala-lang.org/zh-cn/overviews/core/architecture-of-scala-collections.html

//25.1 集合构建器(遍历器: traversal , 构建器: builder)
//example: builder类
package scala.collection.generic
class Builder[-Elem,+To]{
	def +=(elem:Elem): this.type
	def result():To
	def clear()
	def mapResult[NewTo](f:To=>NewTo):Builder[Elem,NewTo]=...
}
//用mapResult来产生一个构建数组的构建器
val buf = new ArrayBuffer[Int]
val bldr = buf mapResult (_.toArray)

//25.2 抽取公共操作 P567
//example:TraversableLike中的filter实现
package scala.collection
trait TraversableLike[+Elem,+Repr]{
	def newBuilder:Builder[Elem,repr]
	def foreach[U](f:Elem=>U) ...
	def filter(p:Elem=>Boolean):Repr={
		val b=newBuilder
		foreach{elem=>if(p(elem)) b+=elem}
		b.result}
}

//example:with map
import collection.immutable.BitSet
scala> val bits=BitSet(1,2,3)						--->bits: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
scala> bits map (_ *2)							--->res92: scala.collection.immutable.BitSet = BitSet(2, 4, 6)
scala> bits map (_.toFloat)					--->res93: scala.collection.immutable.SortedSet[Float] = TreeSet(1.0, 2.0, 3.0)

//example:map case操作 map反转&交出键值
scala> Map("a"->1,"b"->2) map {case (x,y)=>(y,x)}			--->res94: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a)
scala> Map("a"->1,"b"->2) map {case (x,y)=>y}				--->res95: scala.collection.mutable.Iterable[Int] = ArrayBuffer(2, 1)


//ex:TraversableLike中map的实现
def map[B,That](f:Elem=>B)(implicit bf:CanBuildFrom[Repr,B,That]):That={	//CanBuildFrom:构建器工厂
	val b = bf(this)
	for (x<-this) b+=f(x)
	b.result
}

//ex:CanBuildFrom特质 P570
package scala.collection.generic
trait CanBuildFrom[-From,-Elem,+To]{def apply(from:From):Builder[Elem,To]}

//
val xs: Iterable[Int]=List(1,2,3)
val ys=xs map(x=>x*x)


//25.3 集成新集合 P572
//25.3.1 集成序列
abstract class Base
case object A extends Base
case object T extends Base
case object G extends Base
case object U extends Base
object Base {
	val fromInt:Int=Base=>Array(A,T,G,U)
	val toInt:Base=Int=>Map(A->0,T->1,G->2,U->3)
}

//ex:RNA 链条类 最终版
import collection.IndexedSeqLike
import collection.mutable.{Builder, ArrayBuffer}
import collection.generic.CanBuildFrom

final class RNA private (val groups:Array[Int],val length:Int) extends IndexedSeq[Base] with IndexedSeqLike[Base,RNA]{
	import RNA._
	override protected[this] def newBuilder:Builder[Base,RNA]=RNA.newBuilder
	def apply(idx:Int):Base={
		if(idx<0 || length<=idx) throw new IndexOutOfBoundsException
		Base.fromInt(groups(idx/N) >> (idx % N * S) & M)
	}
	override def foreach[U](f:Base=>U):Unit={
		var i=0
		var b=0
		while (i<length){
			b = if(i % N == 0) groups(i/N) else b>>>S
			f(Base.fromInt(b & M))
			i+=1
		}
	}
}
//RNA伴生对象
object RNA {
	private val S = 2			// group中的比特(bit)数
	private val M = (1 << S) - 1		// 用于隔离group的比特掩码
	private val N = 32 / S			// 一个Int中的group数
	def fromSeq(buf: Seq[Base]): RNA = {
		val groups = new Array[Int]((buf.length + N - 1) / N)
		for (i <- 0 until buf.length) groups(i / N) |= Base.toInt(buf(i)) << (i % N * S)
		new RNA(groups, buf.length)
	}
	def apply(bases: Base*) = fromSeq(bases)
	def newBuilder: Builder[Base, RNA] =new ArrayBuffer mapResult fromSeq
	implicit def canBuildFrom: CanBuildFrom[RNA, Base, RNA] =new CanBuildFrom[RNA, Base, RNA] {
		def apply(): Builder[Base, RNA] = newBuilder
		def apply(from: RNA): Builder[Base, RNA] = newBuilder
	}
}

//25.3.2 继承新的集和映射 P584
//ex: 用Patricia trie实现前缀映射
import collection._
class PrefixMap[T] extends mutable.Map[String, T] with mutable.MapLike[String, T, PrefixMap[T]] {
	var suffixes: immutable.Map[Char, PrefixMap[T]] = Map.empty
	var value: Option[T] = None
	def get(s: String): Option[T] =
		if (s.isEmpty) value
		else suffixes get (s(0)) flatMap (_.get(s substring 1))
	def withPrefix(s: String): PrefixMap[T] =
	if (s.isEmpty) this
	else {
		val leading = s(0)
		suffixes get leading match {
					case None =>suffixes = suffixes + (leading -> empty)
					case _ =>
		}
	suffixes(leading) withPrefix (s substring 1)
	}
	override def update(s: String, elem: T) = withPrefix(s).value = Some(elem)
	override def remove(s: String): Option[T] =
		if (s.isEmpty) { val prev = value; value = None; prev }
		else suffixes get (s(0)) flatMap (_.remove(s substring 1))
	def iterator: Iterator[(String, T)] =
		(for (v <- value.iterator) yield ("", v)) ++
		(for ((chr, m) <- suffixes.iterator;
		(s, v) <- m.iterator) yield (chr +: s, v))
	def += (kv: (String, T)): this.type = { update(kv._1, kv._2); this }
	def -= (s: String): this.type = {remove(s); this }
	override def empty = new PrefixMap[T]
}

//prefix map的伴生对象
import scala.collection.mutable.{Builder, MapBuilder}
import scala.collection.generic.CanBuildFrom
object PrefixMap extends {
	def empty[T] = new PrefixMap[T]
	def apply[T](kvs: (String, T)*): PrefixMap[T] = {
		val m: PrefixMap[T] = empty
		for (kv <- kvs) m += kv
		m
	}
	def newBuilder[T]: Builder[(String, T), PrefixMap[T]] =
		new MapBuilder[String, T, PrefixMap[T]](empty)
		implicit def canBuildFrom[T]: CanBuildFrom[PrefixMap[_], (String, T), PrefixMap[T]] =
			new CanBuildFrom[PrefixMap[_], (String, T), PrefixMap[T]] {
				def apply(from: PrefixMap[_]) = newBuilder[T]
				def apply() = newBuilder[T]
			}
}




=============================================================Chapter 26 提取器
//26.1 示例:提取电子邮箱 P589
def isMail(s:String):Boolean
def domain(s:String):String
def user(s:String):String
--->
if (isMail(s)) println(user(s)+" AT "+domain(s)) else println(" not an email address ")
--->
s match {
	case EMail(user,domain)=>println(user+" AT "+domain)
	case _ =>println("not an email address")
}

//26.2 提取器
//ex:Email字符串提取器对象
object EMail{
	def apply(user:String,domain:String)=user+"@"+domain
	def unapply(str:String):Option[(String,String)]={
		val parts=str split "@"
		if (parts.length==2) Some(parts(0),parts(1)) else None
	}
}

//26.3 提取0或1个变量的模式
//ex:Twice字符串提取对象
object Twice{
	def apply(s:String):String=s+s
	def unapply(s:String):Option[String]={
		val length=s.length/2
		val half=s.substring(0,length)					//截断
		if (half==s.substring(length)) Some(half) else None		//判断对折后是否相等
	}
}
//ex:UpperCase字符串提取对象
object UpperCase {def unapply(s:String):Boolean=s.toUpperCase == s}
//example:测试邮件名重复的函数
def userTwiceUpper(s:String)=s match {
	case EMail(Twice(x@UpperCase()),domain)=>"match: "+x+" in domain "+domain
	case _ =>"no match"
}
//
scala> userTwiceUpper("HAHA@qq.com")					--->res97: String = match: HA in domain qq.com
scala> userTwiceUpper("HAA@qq.com")					--->res98: String = no match


//26.4 提取可变长度参数的模式
dom match {
	case Domain("org","acm")=>println("acm.org")
	case Domain("com","sun","java")=>println("java.sun.com")
	case Domain("net",_*)=>println("a.net domain")
}

//ex: Domain字符串提取器对象
object Domain{
	def apply(parts:String):String=parts.reverse.mkString(".")
	def unapplySeq(whole:String):Option[Seq[String]]=Some(whole.split("\\.").reverse)
}

//example:tom的电子邮件
def isTom(s:String):Boolean=s match{
	case EMail("tom",Domain("com",_*))=>true
	case _ => false
}
//test:
scala> isTom("acctom@198.com")						--->res121: Boolean = false
scala> isTom("tom@198.com")						--->res122: Boolean = true

//ex:ExpandedEmail字符串提取器对象
object ExpandedEmail {
	def unapplySeq(email:String):Option[(String,Seq[String])]={
		val parts=email split "@"
		if (parts.length==2) Some(parts(0),parts(1).split("\\.").reverse)
		else None
	}
}
//tets:
scala> val s = "tom@sina.allc.ch"					--->s: String = tom@sina.allc.ch
scala> val ExpandedEmail(name,topdom,subdoms @ _*)=s
	name: String = tom
	topdom: String = ch
	subdoms: Seq[String] = WrappedArray(allc, sina)


//26.5 提取器和序列模式 P598
//ex:定义了unapplySeq的提取器
package scala
object List{
	def apply[T](elems:T*)=elems.toList
	def unapplySeq[T](x:List[T]):Option[Seq[T]]=Some(x)
	...
}

//26.6 提取器和样例类的比对 P599

//26.7 正则表达式
//26.7.1 组织正则表达式
ab?					a后面可能跟着一个b
\d+					一个由单个或多个数字(\d)组成的数
[a-dA-D]\w*				一个有大写或小写字母a到d开始的字母,首字母后是一组0个或更多‘单词字符’(\w)
(-)?(\d+)(\.\d*)?			一个由可选的负号(_),一个或多个数字,后面可能跟着一段小数点加上0个或更多数字组成的数。该数字包含三个组,即负号 小数点部分和包含小数点的部分。组被括在元括号中

import scala.util.matching.Regex
val decimal=new Regex("(-)?(\\d+)(\\.\\d*)?")
val decimal=new Regex("""(-)?(\d+)(\.\d*)?""")
val decimal="""(-)?(\d+)(\.\d*)?""".r

//ex: StringOps中r的定义
package scala.runtime
import scala.util.matching.Regex
class StringOps(self:String)... {
	...
	def r = new Regex(self)
}

//26.7.2 查找正则表达式
regex findFirstIn str				在字符串str中查找正则表达式regex,以Option类型返回结果
regex findAllIn str				在字符串str中查找正则表达式regex,以Iterator的形式返回结果
regex findPrefixOf str				在字符串str的一开始查找正则表达式regex,以Option的形式返回

//example:
val decimal="""(-)?(\d+)(\.\d*)?""".r
val input="for -1.0 to 99 by 3"
for (s<-decimal findAllIn input) println(s)
scala> decimal findFirstIn input					--->res132: Option[String] = Some(-1.0)
scala> decimal findPrefixOf input					--->res133: Option[String] = None

//26.7.3 用正则表达式提取信息
scala> val decimal(sign,integerpart,decimalpart)="-1.23"
	sign: String = -
	integerpart: String = 1
	decimalpart: String = .23

scala> val decimal(sign,integerpart,decimalpart)="1.0"
	sign: String = null
	integerpart: String = 1
	decimalpart: String = .0

scala> for (decimal(s,i,d)<- decimal findAllIn input) println("sign: "+s+", integer: "+i+", decimal: "+d)
	sign: -, integer: 1, decimal: .0
	sign: null, integer: 99, decimal: null
	sign: null, integer: 3, decimal: null



=============================================================Chapter 27 注解
//28.1 why we use annotation 	p606	
//27.2 注解的语法
@deprecated def bigMistake()=// ...
(e: @unchecked) match{ ... }
@annot(exp1,exp2...)
@cool val normal="Hello"\

import annotation._
class strategy(arg:Annotation) extends Annotation
class delayed extends Annotation
//@strategy(@delayed) def f()={}
@strategy(new delayed) def f()={}
//27.3 标准注解
deprecated,volatile,serializable,BeanProperty,tailrec,unchecked
//27.3.1 过时(deprecation)
@deprecated def bigMistake()=// ...
//27.3.2 易失(volatile)字段
@volatile
//27.3.3 二进制序列化 p611
//27.3.4 自动的get和set方法
@scala.reflect.BeanProperty
//27.3.5 尾递归(tailrec)
//27.3.6 不检查(unchecked)
//27.3.7 本地(native)方法

=============================================================Chapter 28 使用XML
//28.1 半结构化数据 P614
//28.2 XML概览
<pod>three<peas></peas> in the <pod>
<pod>three<peas/> in the </pod>
//28.3 XML字面量
scala> <a>
     | this is some XML
     | Here is a tag:<atag/>
     | </a>
--->	res0: scala.xml.Elem =
	<a>
	this is some XML
	Here is a tag:<atag/>
	</a>
//
scala> <A>{"hello"+", kitty"}</A>				--->res1: scala.xml.Elem = <A>hello, kitty</A>
//example:条件判断
scala> <a> {if (year<2000) <old>{year}</old> else xml.NodeSeq.Empty} </a>
--->	res3: scala.xml.Elem =<a> <old>1998</old> </a>

scala> <a> {3+5} </a>						--->res4: scala.xml.Elem = <a> 8 </a>


//28.4 序列化
abstract class Ctherm{
	val desc:String
	val year:Int
	val dateObtain:String
	val bookPrice:Int
	val purchasePrice:Int
	val condition:Int
	override def toString=desc
}

abstract class CCtherm{
	val desc:String
	val year:Int
	val dateObtain:String
	val bookPrice:Int
	val purchasePrice:Int
	val condition:Int
	override def toString=desc
	def toXml=
		<cctherm>
			<desc>{desc}</desc>	
			<year>{year}</year>
			<dateObtain>{dateObtain}</dateObtain>
			<bookPrice>{bookPrice}</bookPrice>
			<purchasePrice>{purchasePrice}</purchasePrice>
			<condition>{condition}</condition>
		</cctherm>
}
//example:toXML
val therm = new CCtherm{
	val desc = "im zieox #22"
	val year = 2018
	val dateObtain = "October 11 2018"
	val bookPrice=17988
	val purchasePrice=56332
	val condition=11
}

scala> therm.toXml
--->	res10: scala.xml.Elem =
		<cctherm>
			<desc>im zieox #22</desc>
			<year>2018</year>
			<dateObtain>October 11 2018</dateObtain>
			<bookPrice>17988</bookPrice>
			<purchasePrice>56332</purchasePrice>
			<condition>11</condition>
		</cctherm>


//28.5 拆解XML
//28.5.1 xml提取文本
scala> <a> Sounds <tag/> good</a>.text					--->res11: String = " Sounds  good"
scala> <a> --->&gt; output </a>.text					--->res14: String = " --->> output "
//28.5.2 xml提取子元素
scala> <a><b><c>hello</c></b></a> \"b"				--->res15: scala.xml.NodeSeq = NodeSeq(<b><c>hello</c></b>)
scala> <a><b><c>hello</c></b></a> \"c"				--->res16: scala.xml.NodeSeq = NodeSeq()
scala> <a><b><c>hello</c></b></a> \\"c"				--->res17: scala.xml.NodeSeq = NodeSeq(<c>hello</c>)
scala> <a><b><c>hello</c></b></a> \"a"				--->res18: scala.xml.NodeSeq = NodeSeq()
scala> <a><b><c>hello</c></b></a> \\"a"				--->res19: scala.xml.NodeSeq = NodeSeq(<a><b><c>hello</c></b></a>)
//28.5.3 提取属性 
val zieox =
	<emp
	name="zieox"
	rank="champion"
	code="00000001"/>

scala> zieox \ "@name"						--->res26: scala.xml.NodeSeq = zieox


//28.6 反序列化
//ex:通过Node反序列化
def fromXML(node:scala.xml.Node):CCtherm = 
	new CCtherm{
		val desc = (node \  "desc").text
		val year = (node \  "year").text.toInt
		val dateObtain = (node \  "dateObtain").text
		val bookPrice = (node \  "bookPrice").text.toInt
		val purchasePrice = (node \  "purchasePrice").text.toInt
		val condition = (node \  "condition").text.toInt
	}
val node =therm.toXml
scala> fromXML(node)						--->res27: CCtherm = im zieox #22


//28.7 加载和保存 XML.save / XML.loadFile
scala.xml.XML.save("therm1.xml",node)
scala> val loadnode=xml.XML.loadFile("therm1.xml")
	loadnode: scala.xml.Elem =
		<cctherm>
			<desc>im zieox #22</desc>
			<year>2018</year>
			<dateObtain>October 11 2018</dateObtain>
			<bookPrice>17988</bookPrice>
			<purchasePrice>56332</purchasePrice>
			<condition>11</condition>
		</cctherm>

//28.8 对XML做模式匹配 P624
def proc(node:scala.xml.Node):String=
	node match{
		case <a>{contents}</a> => "It's an a: "+contents
		case <b>{contents}</b> => "It's a b: "+contents
		case _ => "It's something else."
	}

scala> proc(<a>apple</a>)					--->res31: String = It's an a: apple
scala> proc(<b>apple</b>)					--->res32: String = It's a b: apple
scala> proc(<a>a<em>red</em>apple</a>)				--->res33: String = It's something else.
scala> proc(<a/>)						--->res35: String = It's something else.

//exL: 添加_*表示任何节点
def proc(node:scala.xml.Node):String=
	node match{
		case <a>{contents @_*}</a> => "It's an a: "+contents
		case <b>{contents @_*}</b> => "It's a b: "+contents
		case _ => "It's something else."
	}

scala> proc(<a>a<em>red</em>apple</a>)				--->res37: String = It's an a: ArrayBuffer(a,<em>red</em>,apple)
//ex:catalog元素里有2个节点,在这2个元素之前 之后都有空白
val catalog=
//<core>
	<catalog>
		<CCtherm>
			<desc>hot dog</desc>
			<year>1999</year>
			<dateObtain>March 22,1999</dateObtain>
			<bookPrice>500</bookPrice>
			<purchasePrice>2669</purchasePrice>
			<condition>9</condition>
		</CCtherm>
		<CCtherm>
			<desc>fucknig girl</desc>
			<year>2009</year>
			<dateObtain>March 28,1999</dateObtain>
			<bookPrice>5000</bookPrice>
			<purchasePrice>2869</purchasePrice>
			<condition>9</condition>
		</CCtherm>
	</catalog>
/*	<catalog>
		<CCtherm>
			<desc>fuck</desc>
			<year>2000</year>
			<dateObtain>March 1,1911</dateObtain>
			<bookPrice>500</bookPrice>
			<purchasePrice>2669</purchasePrice>
			<condition>9</condition>
		</CCtherm>
		<CCtherm>
			<desc>girl</desc>
			<year>2019</year>
			<dateObtain>March 24,1909</dateObtain>
			<bookPrice>5000</bookPrice>
			<purchasePrice>2869</purchasePrice>
			<condition>9</condition>
		</CCtherm>
	</catalog>
</core>	
*/
catalog match{case <catalog>{therms @_*}</catalog> =>for (therm<-therms) println("processing: "+(therm \ "desc").text)}
//catalog match{case <core>{therms @_*}</core> =>for (therm<-therms) println("processing: "+(therm \ "desc").text)}

===>改进
catalog match 
{case <catalog>{therms @ _*}</catalog>=>for (therm @ <cctherm>{_*}</cctherm> <-therms) println("processing: "+(therm \ "desc").text)}
	
	


=============================================================Chapter 29 用对象实现模块化功能
//26.1 问题描述 P630
//26.2 食谱应用程序
//ex:food类
package org.stairwaybook.recipe
abstract class Food(val name:String){override def toString=name}
//ex:recipe实体类
package org.stairwaybook.recipe
class Recipe(
	val name:String,
	val ingredients:List[Food],
	val instructions:String
	){override def toString=name}
//ex:
package org.stairwaybook.recipe
object apple extends Food("apple")
object orange extends Food("orange")
object cream extends Food("cream")
object sugar extends Food("sugar")
object salad extends Recipe("fruit salad",List(apple,orange,cream,sugar),"Stir it together")


//ex:模拟数据库和浏览器模块
package org.stairwaybook.recipe
object SimpleDatabase {
	def allfoods = List(apple,orange,cream,sugar)
	def foodname(name:String):Option[Food]=allfoods.find(_.name==name)
	def allRecipes:List[Recipe]=List(salad)
}
object SimpleBrowser{def recipesUsing(food:Food)=SimpleDatabase.allRecipes.filter(recipe=>recipe.ingredients.contains(food))}

//ex:对食物进行分类的数据库和浏览模块
package org.stairwaybook.recipe
object SimpleDatabase{
	def allFoods= List(apple,orange,cream,sugar)
	def foodName(name:String):Option[Food]=allFoods.find(_.name==name)
	def allRecipes:List[Recipe]=List(salad)
	case class FoodCategory(name:String,foods:List[Food])
	private var categories=List(
		FoodCategory("fruits",List(apple,orange)),
		FoodCategory("misc",List(cream,sugar)))
	def allcategories=categories
}
object SimpleBrowser{
	def recipesUsing(food:Food)=SimpleDatabase.allRecipes.filter(recipe=>recipe.ingredients.contains(food))
	def displayCategory(category:SimpleDatabase.FoodCategory)={println(category)}
}


//29.3 抽象 P634
//ex:带有抽象数据库val的Browser类
abstract class Browser{
	val database:Database
	def recipesUsing(food:Food)=Database.allRecipes.filter(recipe=>recipe.ingredients.contains(food))
	def displayCategory(category:Database.FoodCategory)={println(category)}
}
	
//ex:带有抽象方法的Datebase类	
abstract class Database{
	def allFoods:List[Food]
	def allRecipes:List[Recipe]
	def foodNamed(name:String)=allFoods.find(f=>f.name==name)
	case class FoodCategory(name:String,foods:List[Food])
	def allCategories:List[FoodCategory]
}
	
//ex: 作为Database子类的SimpleDatabase 对象	
object SimpleDatabase extends Database {
	def allFoods=List(apple,orange,cream,sugar)
	def allRecipes:List[Recipe]=List(salad)
	private var categories=List(
		FoodCategory("fruits",List(apple,orange)),
		FoodCategory("misc",List(cream,sugar)))
	def allCategories=categories
}

------tes
scala> val apple=SimpleDatabase.foodNamed("apple").get					--->apple: Food = apple
scala> SimpleBrowser.recipesUsing(apple)						res176: List[Recipe] = List(fruit salad)

//ex:作为Browser子类的SimpleBrowser对象
object SimpleBrowser extends Browser{val database = SimpleDatebase}


//ex:学生数据库和浏览器
object StudentDatabase extends Database {
	object FrozenFood extends Food("FrozenFood")
	object HealthUp extends Recipe(
		"heat it up",
		List(FrozenFood),
		"Microwave the 'food' for 10 minutes.")
	def allFoods = List(FrozenFood)
	def allRecipes=List(HealthUp)
	def allCategories=List(FoodCategory("edible",List(FrozenFood)))
}
object StudentBrowser extends Browser{val databse=StudentDatabase}


//29.4 将模块拆分为特质
//ex:用于表示食物类目的特质
trait FoodCategories{
	case class FoodCategory(name:String,foods:List[Food])
	def allCategories:List[FoodCategory]
}

//ex:混入FoodCategories特质的Database类
abstract class Database extends FoodCategories{
	def allFoods:List[Food]
	def allRecipes:List[Recipe]
	def foodNamed(name:String)=allFoods.find(f=>f.name==name)
}

//ex:完全由混入特质组成的SimpleDatabase对象
object SimpleDatabase extends Database with SimpleFoods with SimpleRecipes

//ex:SimpleFoods特质
trait SimpleFoods{
	object pear extends Food("Pear")
	def allFoods = List(apple,pear)
	def allCategories=Nil
}

//ex: 带有自类型的SimpleRecipes特质 P639
trait SimpleRecipes{
	this: SimpleFoods => object salad extends Recipe("fruit salad",List(apple,pear),"mix it all together.")
	def allRecipes=List(salad)
}


//29.5 运行时链接
//动态选择模块实现的应用
object GotApples{
	def main(args:Array[String])={
		val db:Database=
			if (args(0)=="student") StudentDatabase
			else SimpleDatebase 
		object browser extends Browser {val database=db}
		val apple=SimpleDatabase.foodNamed("apple").get
		for (recipe<- browser.recipesUsing(apple)) println(recipe)
	}
}
	
//29.6 跟踪模块实例 P642

//ex:使用单例类型
object browser extends Browser{val database :db.type=db}	// .type表示单例类型




=============================================================Chapter 30 对象相等性
https://booksites.artima.com/programming_in_scala_2ed/examples/html/ch30.html
//30.1 Scala中的相等性 P645
//ex:==方法
final def ==(that:Any):Boolean=if (null eq this){null eq that} else {this equals that}

//30.2 编写相等性方法
//重写equals方法时有四个常见陷阱
#30.2.1 以错误的签名定义equals方法 P647
class Point(val x:Int,val y:Int){/*def toString():int=x+y*/}
//重写equals
override def equals(other:Any)=other match {
	case that :Point=>this.x==that.x && this.y==that.y
	case _ =>false 
}

#30.2.2 修改equals但没有同时修改hashCode
class Point(val x:Int,val y:Int){
	override def hashCode=(x,y).##
	override def equals(other:Any)=other match{
		case thqat:Point=>this.x==that.x && this .y == that.y
		case _ => false 
	}
}

#30.2.3 用可变字段定义equals
class Point(var x:Int,var y:Int){
	override def hashCode=(x,y).##
	override def equals(other:Any)=other match{
		case that:Point=>this.x==that.x && this .y == that.y
		case _ => false 
	}
}

------------------------------------------tets---------------------------------------------------
scala> val a,b=new Point(1,2)
	a: Point = Point@5428bd62
	b: Point = Point@5428bd62
scala> a eq b							--->res185: Boolean = false
scala> a equals b						--->res186: Boolean = true
scala> val col=collection.mutable.HashSet(a)
	col: scala.collection.mutable.HashSet[Point] = Set(Point@5428bd62)
scala> col contains a						--->res0: Boolean = true
scala> col contains b						--->res1: Boolean = true
-------------------------------------------------------------------------------------------------

#30.2.4 未能按等同关系equals方法 P652
import scala.Enumeration
object Color extends Enumeration {val Red,Orange,Yellow,Green,Blue,Indigo,Violet=Value}

//粗糙的ColoredPoint
class ColoredPoint(x:Int,y:Int,val color:Color.Value) extends Point(x,y){
	override def equals(other:Any)=other match {
		case that:ColoredPoint=>this.color==that.color && super.equals(that)
		case _ => false
	}
}
----------------------------------------------test-----------------------------------------------------------
scala> val p = new Point(1,2)					--->p: Point = Point@5428bd62
scala> val cp = new ColoredPoint(1,2,Color.Red)			--->cp: ColoredPoint = ColoredPoint@5428bd62
scala> p eq cp							--->res8: Boolean = false
scala> cp eq p							--->res9: Boolean = false
-------------------------------------------------------------------------------------------------------------

//改进后的ColoredPoint
class ColoredPoint(x:Int,y:Int,val color:Color.Value) extends Point(x,y){
	override def equals(other:Any)=other match {
		case that:ColoredPoint=>(this.color==that.color) && super.equals(that)
		case that:Point=>that equals this 
		case _ => false
	}
}
----------------------------------------------test-----------------------------------------------------------
scala> p equals cp 						--->res11: Boolean = true
scala> cp equals p 						--->res12: Boolean = true
val r=new ColoredPoint(1,2,Color.Red)
val b=new ColoredPoint(1,2,Color.Blue)
scala> r==p							--->res13: Boolean = true
scala> r==b							--->res14: Boolean = false
scala> r==cp							--->res15: Boolean = true
-------------------------------------------------------------------------------------------------------------
P656

//ex: 调用了canEqual的超类equals方法
class Point(val x:Int,val y:Int){
	override def hashCode=(x,y).##
	override def equals(other:Any)=other match {
		case that:Point=>(that canEqual this) && (this.x==that.x) && (this.y==that.y)
		case _ => false 
	}
	def canEqual(other:Any)=other.isInstanceOf[Point]
}

//调用canEqual的子类equals方法
class ColoredPoint(x:Int,y:Int,val color:Color.Value) extends Point(x,y){
	override def hashCode=(super.hashCode,color).##
	override def equals(other:Any)=other match{
		case that:ColoredPoint=>(that canEqual this) && super.equals(that) && this.color==that.color
		case _ => false 
	}
	override def canEqual(other:Any)=other.isInstanceOf[ColoredPoint]
}

----------------------------------------------test-----------------------------------------------------------
scala> val p = new Point(1,2)					--->p: Point = Point@5428bd62
scala> val cp= new ColoredPoint(1,2,Color.Indigo)		--->cp: ColoredPoint = ColoredPoint@e6230d8f
val pAnon=new Point(1,1){override val y = 2}
val coll =List(p)
scala> coll contains p						--->res1: Boolean = true
scala> coll contains cp						--->res2: Boolean = false
scala> coll contains pAnon					--->res3: Boolean = true
-------------------------------------------------------------------------------------------------------------


//30.3 为参数化类型定义相等性
//ex:二叉树的继承关系
trait Tree[+T]{
	def elem:T
	def left:Tree[T]
	def right:Tree[T]
}
object EmptyTree extends Tree[Nothing]{
	def elem=throw new NoSuchElementException("EmptyTree.elem")
	def left=throw new NoSuchElementException("EmptyTree.left")
	def right=throw new NoSuchElementException("EmptyTree.right")
}
class Branch[+T](val elem:T,val left:Tree[T],val right:Tree[T]) extends Tree[T]

//ex:添加equals的Branch
class Branch[+T](val elem:T,val left:Tree[T],val right:Tree[T]) extends Tree[T]{
	override def equals(other:Any)=other match{
		case that:Branch[_]=>this.elem==that.elem && this.left=that.left && this.right=that.right
		case _ =>false
	}
}

//ex:带有equals和hashCode的参数化类型
class Branch[T](val elem: T,val left: Tree[T],val right: Tree[T]) extends Tree[T] {
	override def equals(other: Any) = other match {
		case that: Branch[_] => 
					(that canEqual this) && 
					this.elem == that.elem && 
					this.left == that.left &&
					this.right == that.right
		case _ => false
	}
	def canEqual(other: Any) = other.isInstanceOf[Branch[_]]
	override def hashCode: Int = 41 * (41 * (41 + elem.hashCode) + left.hashCode) + right.hashCode
}




//30.4 如何编写equals和hashCode方法	P664
//带有equlas和hashCode的Rational类
class Rational(n: Int, d: Int) {
	require(d != 0)
	private val g = gcd(n.abs, d.abs)
	val numer = (if (d < 0) -n else n) / g
	val denom = d.abs / g  
	private def gcd(a: Int, b: Int): Int =if (b == 0) a else gcd(b, a % b)
	override def equals(other: Any): Boolean = other match {
			case that: Rational => (that canEqual this) && numer == that.numer && denom == that.denom
			case _ => false
	}
	def canEqual(other: Any): Boolean =other.isInstanceOf[Rational]
	override def hashCode: Int =41 * (41 + numer) + denom
	override def toString = if (denom == 1) numer.toString else numer +"/"+ denom
}
//如何编写equlas	P665
//如何编写hashCode	P667



=============================================================Chapter 31 结合Scala和Java
//31.1 从Java使用Scala P669
//一般原则
//值类型
//单例对象
object App{
  def a(x:Int,y:String)={println(y+":"+x*x)}
  def main(args:Array[String]) ={println(a(10,"zieox"))}
}
//作为接口的特质

//31.2 注解
//1. 标准注解的额外效果P672
//2. 过期 @deprecated
//3. Volatile 字段 @volatile
//4. 序列化 @serializable
//5. 抛出的异常 throws
//ex:声明了对应Java中throws子句的Scala方法
import java.io._
class Reader(fname:String){
	private val in = new BufferedReader(new FileReader(fname))
	@throws(classOf[IOException])
	def read()=in.read()
}

//6. Java注解
import org.junit.Test
import org.junit.Assert.assertEquals
class SetTest{
	@test
	def testMultiAdd={
		val set = Set()+1+2+3+1+2+3
		assertEquals(3,set.size)
	}
}

//7. 编写你自己的注解 P676	


//31.3 通配类型
//ex:一个简单的带通配类型的java类
public class Wild{
	public Collection<?> contents(){
		Collection<String> stuff = new Vector<String>();
		stuff.add(a);stuff.add("b");stuff.add("see");
		return stuff;
	}
}

//31.4 同时编译Scala和Java P6880

//34.5 基于Scala2.12特性的Java 8集成
//1. Lambda表达式和"SAM"类型
//example:JButton & Lambda
JButton button = new JButton();
button.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){spstem.out.println("pressed");}})
--->
JButton button=new JButton();
button.addActionListener(event->System.out.println("pressed!"));
--->
val button=new JButton
button.addActionListener( _ => println("pressed!"));

//SAM
trait increaser{def increaser(i:Int):Int}	//声明一个带有抽象increaser方法的特质
def increaseone(increaser:increaser):Int=increaser.increaser(1)	//
increaseone(new increaser{def increaser(i:Int):Int=i+7})
--->
increaseone(i=>i+7)

//2. 从Scala2.12使用Java8的Stream(使用Stream)
import java.util.function.IntUnaryOperator
import java.util.Arrays
//byJava
val stream=Arrays.stream((1 to 10).toArray)
scala> stream.map(i=>i+1).toArray				--->res30: Array[Int] = Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
//byScala
val f=(i:Int)=>i+1
scala> val t=List.range(1,20,3)					--->t: List[Int] = List(1, 4, 7, 10, 13, 16, 19)
scala> t map f							--->res2: List[Int] = List(2, 5, 8, 11, 14, 17, 20)
//or
stream.map(i=>f(i)).toArray
scala> stream.map(i=>f(i)).toArray				--->res7: Array[Int] = Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
//or
val f:IntUnaryOperator = i=>i+1
val stream = Arrays.stream(Array.range(1,20,3))
scala> stream.map(f).toArray					--->res8: Array[Int] = Array(2, 5, 8, 11, 14, 17, 20)



=============================================================Chapter 32 Future和并发编程
//32.1 天堂里的烦恼 P687
//32.2 异步执行和Try
import scala.concurrent.Future
val fut = Future{Thread.sleep(10000);21+21}			--->error
//引入scala提供的一个全局的执行上下文,对jvm而言,这个全局的执行上下文使用的是一个线程池

import scala.concurrent.ExecutionContext.Implicits.global
//ex:basic1
scala> val fut = Future{Thread.sleep(10000);21+21}
		--->fut: scala.concurrent.Future[Int] = Future(<not completed>)
#10s later
scala> fut.isCompleted
		--->res3: Boolean = true
scala> fut.value
		-->res4: Option[scala.util.Try[Int]] = Some(Success(42))

//table:Try 继承关系图
scala.util Success[T] final case--->scala.util Try[+T] sealed abstract<---scala.util Failure[T] final case

//恶习:basic2
val fut=Future{Thread.sleep(10000);21/0}
scala> fut.value
		--->res5: Option[scala.util.Try[Int]] = None
scala> fut.value
		--->res6: Option[scala.util.Try[Int]] = Some(Failure(java.lang.ArithmeticException: / by zero))


//32.3 使用Future
//32.3.1 用map对Future做变换
val fut = Future{Thread.sleep(10000);21+21}
val result = fut.map(x=>x+1)
scala> result.value				--->res11: Option[scala.util.Try[Int]] = Some(Success(43))

//32.3.2 用for表达式对Future做变换
val f1=Future{Thread.sleep(10000);21+11}
val f2=Future{Thread.sleep(10000);22+88}

scala> val t=for (x<-Future{Thread.sleep(10000);21+11};y<-Future{Thread.sleep(10000);22+88}) yield x+y
		--->t: scala.concurrent.Future[Int] = Future(<not completed>)
scala> t.value					--->res27: Option[scala.util.Try[Int]] = Some(Success(142))

//32.3.3 创建Future:Future.failed,Future.successful,Future.fromTry,Promise
scala> Future.successful{11+11}
		--->res28: scala.concurrent.Future[Int] = Future(Success(22))
scala> Future.failed(new Exception("bummer!"))
		--->res29: scala.concurrent.Future[Nothing] = Future(Failure(java.lang.Exception: bummer!))
import scala.util.{Success,Failure}
scala> Future.fromTry(Success{11+11})
		--->res30: scala.concurrent.Future[Int] = Future(Success(22))
scala> Future.fromTry(Failure(new Exception("bummer")))
		--->res31: scala.concurrent.Future[Nothing] = Future(Failure(java.lang.Exception: bummer))

//Promise
#创建Future最一般化的方式是使用Promise。给定一个promise,可以得到一个由这个promise控制的future,当你完成promise时,future也会完成
import scala.concurrent.Promise
scala> val pro = Promise[Int]
		--->pro: scala.concurrent.Promise[Int] = Future(<not completed>)
scala> val fut = pro.future
		--->fut: scala.concurrent.Future[Int] = Future(<not completed>)
scala> fut.value
		--->res32: Option[scala.util.Try[Int]] = None
#可以用名为success,failure和complete的方法来完成promise

scala> pro.success(11)
		--->res33: pro.type = Future(Success(11))
scala> fut.value
		--->res34: Option[scala.util.Try[Int]] = Some(Success(11))

//32.3.4 过滤:filter和collect
val fut = Future{22}
scala> val valid=fut.filter(res=>res>0)
		--->valid: scala.concurrent.Future[Int] = Future(Success(22))
scala> valid.value
		--->res37: Option[scala.util.Try[Int]] = Some(Success(22))
//withFilter
val valid=for (res<-fut if res>0) yield res
scala> valid.value
		--->res38: Option[scala.util.Try[Int]] = Some(Success(22))
val invalid=for (res<-fut if res<0)yield res
scala> invalid.value
		--->res39: Option[scala.util.Try[Int]] = Some(Failure(java.util.NoSuchElementException: Future.filter predicate is not satisfied))

//collect
scala> val valid=fut collect{case res if res>0 => res+46}
		--->valid: scala.concurrent.Future[Int] = Future(<not completed>)
scala> valid.value
		--->res41: Option[scala.util.Try[Int]] = Some(Success(68))

//32.3.5 处理失败:failed,fallbackTo,recover,recoverWith
scala> val failure=Future{22/0}
		--->failure: scala.concurrent.Future[Int] = Future(<not completed>)
scala> failure.value
		--->res42: Option[scala.util.Try[Int]] = Some(Failure(java.lang.ArithmeticException: / by zero))
scala> val expectedFailure=failure.failed
		--->expectedFailure: scala.concurrent.Future[Throwable] = Future(Success(java.lang.ArithmeticException: / by zero))
scala> expectedFailure.value
		--->res43: Option[scala.util.Try[Throwable]] = Some(Success(java.lang.ArithmeticException: / by zero))


//
如果被调用failed方法的future最终成功乐,failed返回的这个future将以NoSuchElementException失败
scala> val success = Future{22/1}
		--->success: scala.concurrent.Future[Int] = Future(<not completed>)
scala> success.value
		--->res44: Option[scala.util.Try[Int]] = Some(Success(22))
scala> val unexpectedSuccess=success.failed
		--->unexpectedSuccess: scala.concurrent.Future[Throwable] = Future(Failure(java.util.NoSuchElementException: Future.failed not completed with a throwable.))
scala> unexpectedSuccess.value
		--->res45: Option[scala.util.Try[Throwable]] = Some(Failure(java.util.NoSuchElementException: Future.failed not completed with a throwable.))


//fallbackTo
#fallbackTo 方法允许你提供一个额外可选的future,这个future将用于在你调用fallbackTo的那个future失败的情况
//example:
scala> val fallback = failure.fallbackTo(success)
		--->fallback: scala.concurrent.Future[Int] = Future(Success(22))
scala> fallback.value
		--->res46: Option[scala.util.Try[Int]] = Some(Success(22))
//如果被调用的fallbackTo方法的原始future失败了,那么传递给fallbackTo的future(如果失败)会被忽略,fallbackTo返回的那个future会以最初的异常失败
val failedFallback=failure.fallbackTo(Future{val res=42;require(res<0);res})
scala> failedFallback.value
		--->res47: Option[scala.util.Try[Int]] = Some(Failure(java.lang.ArithmeticException: / by zero))

//recover
//recover方法让你可以把失败的future变成成功的future,同时将成功的future结果原样透传。
scala> val recovered=failedFallback recover{case ex:ArithmeticException => -1}
		--->recovered: scala.concurrent.Future[Int] = Future(<not completed>)
scala> recovered.value
		--->res48: Option[scala.util.Try[Int]] = Some(Success(-1))
scala> val uncovered=fallback recover{case ex:ArithmeticException => -1}
		--->uncovered: scala.concurrent.Future[Int] = Future(<not completed>)
scala> uncovered.value
		--->res50: Option[scala.util.Try[Int]] = Some(Success(22))
//同理,如果recover的偏函数并没有对引发原始future最终失败的那个异常有定义,原始的失败会被透传
scala> val alsoUncovered = failedFallback recover {case ex:IllegalArgumentException => -2 }
		--->alsoUncovered: scala.concurrent.Future[Int] = Future(<not completed>)
scala> alsoUncovered.value
		--->res51: Option[scala.util.Try[Int]] = Some(Failure(java.lang.ArithmeticException: / by zero))

//recoverWith
//like recover,不过它并不是像recover那样恢复成某个值,而是允许你恢复成一个future
scala> val alsoRecovered=failedFallback recoverWith{case ex:ArithmeticException => Future{22+22}}
		--->alsoRecovered: scala.concurrent.Future[Int] = Future(<not completed>)
scala> alsoRecovered.value
		--->res52: Option[scala.util.Try[Int]] = Some(Success(44))

//32.3.6 同时映射两种可能:transform
//future的tranform方法接受2个函数来对future进行变换:一个用于处理成功,一个用于处理失败
val first = success.transform(res=>res* -1,ex=>new Exception("see cause",ex))
scala> first
		--->res53: scala.concurrent.Future[Int] = Future(Success(-22))
val second=failure.transform(res=>res* -1,ex=>new Exception("see cause,ex"))
scala> second.value
		--->res55: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: see cause,ex))
//example:1
val firstcase=success.transform{
	case Success(res) => Success(res* -1)
	case Failure(ex) => Failure(new Exception("see cause",ex))
}
scala> firstcase.value
		--->res57: Option[scala.util.Try[Int]] = Some(Success(-22))

//example:2
val secondcase=failure.transform{
	case Success(res) => Success(res* -1)
	case Failure(ex) => Failure(new Exception("see cause",ex))
}
scala> secondcase.value
		--->res58: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: see cause))
//example:3
val nonNegative=failure.transform{
	case Success(res)=>Success(res.abs+1)
	case Failure(_)=>Success(0)
}
scala> nonNegative.value
		--->res59: Option[scala.util.Try[Int]] = Some(Success(0))

//32.3.7 组合Future: zip,Future.fold,Fold.reduce,Future.sequence,Future.traverse
scala> val zippedSuccess=success zip recovered
		--->zippedSuccess: scala.concurrent.Future[(Int, Int)] = Future(Success((22,-1)))
scala> val zippedFailure=success zip failure
		--->zippedFailure: scala.concurrent.Future[(Int, Int)] = Future(Failure(java.lang.ArithmeticException: / by zero))
scala> zippedFailure.value
		--->res63: Option[scala.util.Try[(Int, Int)]] = Some(Failure(java.lang.ArithmeticException: / by zero))
//如果两个future都失败了,那么最终失败的那个future将会包含头一个future的异常,也就是被调用zip方法的那一个

//object fold
//future的伴生对象提供了一个fold方法,用来积累TraversableOnce集合中所有的future的结果,并交出以恶搞future的结果。
val f=Future{22+22}
val t=Future{10+10]
scala> val tf=List(t,f)
		--->tf: List[scala.concurrent.Future[Int]] = List(Future(Success(20)), Future(Success(44)))
val folded=Future.foldLeft(tf)(0){(acc,num)=>acc+num}
scala> folded
		--->res66: scala.concurrent.Future[Int] = Future(Success(64))
val reduced=Future.reduceLeft(tf){(acc,num)=>acc+num}
scala> reduced.value
		--->res79: Option[scala.util.Try[Int]] = Some(Success(64))

//Future.sequence:将以一个TraversableOnce的future结合变换成一个由值组成的TraversableOnce的future
val futureList=Future.sequence(tf)
scala> futureList.value
		--->res80: Option[scala.util.Try[List[Int]]] = Some(Success(List(20, 44)))

//Future.traverse:会将任何元素类型的TraversableOnce集合变换成以恶搞由future组成的TraversableOnce并将它“sequence”成一个由值组成的TraversableOnce的future
val traversed=Future.traverse(List(1,2,3)){i=>Future(i)}
scala> traversed.value
		-->res82: Option[scala.util.Try[List[Int]]] = Some(Success(List(1, 2, 3)))

//32.3.8 执行副作用:foreach,onComplete,angThen
failure.foreach(ex=>println(ex))		<===>		for(res<-failure) println(res)
success.foreach(ex=>println(res))		<===>		for(res<-success) println(res)

//注册回调(callabck)函数
import scala.util.{Success,Failure}
success onComplete{
	case Success(res) => println(res)
	case Failure(ex)=>println(ex)
}
		--->scala> 22
failure onComplete{
	case Success(res) => println(res)
	case Failure(ex)=>println(ex)
}
		--->scala> java.lang.ArithmeticException: / by zero
//Future并不保证通过onComplete注册的回调函数的任何执行顺序。可以通过andThen强制回调函数的顺序。
val newFuture=success andThen{
	case Success(res) => println(res)
	case Failure(ex)=>println(ex)
}
scala> newFuture
		--->res98: scala.concurrent.Future[Int] = Future(Success(22))

//transformWith
//可以用一个从Try到Future的函数对future进行变换
val flipped=success.transformWith{
	case Success(res)=>Future{throw new Exception(res.toString)}
	case Failure(ex)=>Future{11+11}
}
scala> flipped.value
		--->res99: Option[scala.util.Try[Int]] = Some(Failure(java.lang.Exception: 22))

//32.4 测试Future
//scala的Future的一个优势是它们能帮你避免阻塞
//ex:
import scala.concurrent.Await
import scala.concurrent.duration._
val fut=Future{Thread.sleep(10000);11+11}
scala> val x = Await.result(fut,10.seconds)	//阻塞调用
		--->x: Int = 22
#Await.result接受一个Future和一个duration,这里duration表示Await.result应该等待多长时间让Future完成,如果到时间未完成则触发

//阻塞被广泛接收的一个场景是对异步代码的执行
import org.scalatest.Matchers._
x should be (22)

import org.scalatest.concurrent.ScalaFutures._
val fut=Future{Thread.sleep(10000);11+11}
fut.futureValue should be (22)

//ex:向scalaTest返回future断言
import org.scalatest.AsyncFunSpec
import scala.concurrent.Future
class AddSpec extends AsyncFunSpec{
	def addSoon(addends:Int*):Future[Int]=Future{addends.sum}
	describe("addSoon"){
		it("will evevntually compute a sum of passed Ints"){
			val futureSum:Future[Int]=addSoon(1,2)
			futureSum map{sum=>assert(sum==3)}
		}
	}
}



=============================================================Chapter 33 组合子解析器 P709
//33.1 示例:算术表达式
//算术表达式解析器
import scala.util.parsing.combinator._
class Arith extends JavaTokenParsers{
	def expr:Parser[Any]=term~rep("+"~term | "~"~term)
	def term:Parser[Any]=factor~rep("*"~factor | "/"~factor)
	def factor:Parser[Any]=floatingPointNumber | "("~expr~")"
}

//33.2 运行你的解析器 P712
object ParseExpr extends Arith{
	def main(args:Array[String])={
		println("input : "+args(0))
		println(parseAll(expr,args(0)))
	}
}

//33.3 基本的正则表达式解析器 P714
//针对java标识符的正则表达式
object MyParsers extends RegexParsers{val ident:Parser[String]="""[a-zA-Z_]""".r}

//33.4 另一个示例:JSON (JavaScript Object Notation)
//一个简单的JSON解析器
import scala.util.parsing.combinator._
class JSON extends JavaTokenParsers{
	def value:Parser[Any]=obj|arr|stringLiteral|floatingPointNumber|"null"|"true"|"false"
	def obj:Parser[Any]="{"~repsep(member,",")~"}"
	def arr:Parser[Any]="["~repsep(value,",")~"]"
	def member:Parser[Any]=stringLiteral~":"~value
}

import java.io.FileReader
object ParseJSON extends JSON {
	def main(args:Array[String])={
		val reader=new FileReader(args(0))
		println(parseAll(value,reader))
	}
}

//33.5 解析器输出 P717
P ^^ f		<==>		P - R -f(R)
//ex
def obj:Parser[Map[String,Any]]="{"~repsep(member,",")~"}" ^^ { case "{"~ms~"}" =>Map()++ms}
case class ~[+A,+B](x:A,y:B){override def toString="("+x+"~"+y+")"}
def obj:Parser[Map[String,Any]]="{"~>repsep(member,",")<~"}" ^^ (Map() ++ _)

//一个完整的返回有意义结果的JSON解析器
import scala.util.parsing.combinator._
class JSON1 extends JavaTokenParsers{
	def obj:Parser[Map[String,Any]]="{"~>repsep(member,",")<~"}" ^^ (Map() ++ _)
	def arr:Parser[List[Any]]="["~>repsep(value,",")<~"]"
	def member:Parser[(String,Any)]=stringLiteral~":"~value ^^ {case name~":"~value=>(name,value)}
	def value:Parser[Any]=(
	obj
	arr
	stringLiteral
	floatingPointNumber ^^ (_.toDouble)
	"null" ^^ (x => null)
	"true" ^^ (x => true)
	"false" ^^ (x => false)
	)
}

--------------------------------------table33.1 组合子解析器汇总---------------------------------------------
"..."							字面量
"...".r							正则表达式
P~Q							顺序组合
P<~Q,P<~Q						顺序组合,只保留左和右
P | Q							备选项
opt(P)							可选项
rep(P)							重复项
repsep(P,Q)						交错在一起的重复项
P ^^ f							结果转换
------------------------------------------------------------------------------------------------------------

//符号名称VS由字母数字组成的名称 P721

//33.6 实现组合子解析器 P723
scala的组合子解析框架的核心位于scala.util.parsing.combinator.Parsers特质中
//解析器输入p725
//解析器结果p725
//Parser类 P726
//给this起别名 P727
//单语言符号解析器 P728
def elem(kind:String,p:Elem=>Boolean)=
	new Parser[Elem]{def apply(in:Input)=if (p(in.first)) Success(in.first,in.rest) else Failure(kind+" expected",in)}
//顺序组合 P729
//备选组合 |
def | (q:=>Parser[T])=new Parser[T]{
	def apply(in:Input)=p(in) match{
		case s1 @ Success(_,_)=>s1
		case failure=>q(in)
	}
}

//处理递归
//结果转换P730
def ^^ [U](f:T=>U):Parser[U] =new Parser[U]{
	def apply(in:Input)=p(in) match{
		case Success(x,in1)=>Success(f(x),in1)
		case failure =>failure
	}
}

//不读取任何输入的解析器
//可选项和重复项 P731
def opt[T](p:=>Parser[T]):Parser[Option[T]]=(p ^^ Some(_) success(None))
def rep[T](p:=>Parser[T]):Parser[List[T]]=(p~rep(p) ^^ {case x~xs=>x :: xs} success(List()))
def repsep[T](p:=>Parser[T],q:=>Parser[Any]):Parser[List[T]]=(p~rep(q~>p) ^^ {case r~rs => r :: rs} success(List()))


//33.7字符串字面量和正则表达式 P732
//33.8 词法分析和解析
scala.util.parsing.combinator.lexical
scala.util.parsing.combinator.syntactical

//33.9 错误报告 P734

//33.10 回溯和LL(1)
解析器组合子在选择不同的解析器时采用回溯(backtracking)的方式



=============================================================Chapter 34 GUI编程
//34.1 第一个Swing程序
import scala.swing._
object FirstSwingApp extends SimpleSwingApplication{
	def top = new MainFrame{
		title="First Swing APP "
		contents=new Button{text="click me"}
	}
}

//34.2 面板和布局
//ex:在面板上组装组件
import scala.swing._
object SecondSwingApp extends SimpleSwingApplication{
	def top = new MainFrame{
		title="Second Swing App"
		val button=new Button{text="click me"}
		val label=new Label{text="No nutton clicks registered"}
		contents=new BoxPanel(Orientation.Vertical){	//BoxPanel的contents属性是一个初始值为空的缓冲器
			contents+=button
			contents+=label
			border=Swing.EmptyBorder(30,30,10,30)	//添加边界
		}
	}
}

//34.3 处理事件
#在scala中订阅事件源source的方法是调用listenTo(source),还有一个事件源取消订阅的方法deafTo(source)
listenTo(button)
//按下按钮将会创建一个事件,即如下样本类的实例
case class Buttonlicked(source:Button)
//为了让你的组件对传入的事件作出响应,你需要向名为reactions的属性添加一个处理器
var nClicks=0
reactions+={case ButtonClicked(b)=> nClicks+1 ; label.text="Number of button clicks: "+nClicks}

//ex:实现一个有响应的Swing应用程序
import scala.swing._
import scala.swing.event._
object ReactiveSwingApp extends SimpleSwingApplication{
	def top = new MainFrame{
		title="Reactive Swing App"
		val button=new Button{text="Click me"}
		val label=new Label{text="No Button clicks registered"}
		contents=new BoxPanel(Orientation.Vertical){
			contents+=button
			contents+=label
			border=Swing.EmptyBorder(30,30,10,30)
		}
		listenTo(button)
		var nClicks=0
		reactions+={case ButtonClicked(b)=> nClicks+1 ; label.text="Number of button clicks: "+nClicks}
	}
}

//34.4 示例:摄氏/华氏转换器
import swing._
import event._
<===>
import scala.swing._
import scala.swing.event._

//ex: 温度转换器的一种实现
/*
import swing._
import event._
object TempConverter extends SimpleSwingApplication{
	def top = new MainFrame{
		title="Celsius/Fahrenheit Converter"
		object celsius extends TextField{columns=5}
		object fahrenheit extends TextFiled{columns=5}
		contents=new FlowPanel{
			contents+=celsius
			contents+=new Label(" celsius = ")
			contents+=fahrenheit
			contents+=new Label(" Fahrenheit")
			border = Swing.EmptyBorder(15,10,10,10)
		}
		listenTo(celsius,fahrenheit)
		reactions+={
			case EditDone(`fahrenheit`)=>
				val f=fahrenheit.text.toInt
				val c=(f-32)*5/9
			case EditDone(`celsius`)=>		//仅当事件源为celsius是匹配
				val c=celsius.text.toInt
				val f=c*9/5+32
			fahrenheit.text=f.toString
		}
	}
}
*/



=============================================================Chapter 35 SCells 试算表
//35.1 可视化框架
//ex:tb35.1试算表代码
package org.stairwaybook.scells
import swing._
class Spreadsheet(val height:Int,val width:Int) extends ScrollPane{
	val table = new Table(height,width){
		rowHeight=25
		autoResizeMode=Table.AutoResizeMode.Off
		showGrid=true
		gridColor=new java.awt.Color(150,150,150)
	}
	val rowHeader = new ListView((0 until height) map (_.toString)){
		fixedCellWidth=30
		fixedCellHeight=table.rowHeight
	}
	viewportView=table
	rowHeaderView=rowHeader
}
//试算表应用的主程序
object Main extends SimpleSwingApplication{
	def top = new MainFrame{
		title = "ScalaSheet"
		contents = new Spreadsheet(100,20)
	}
}

//35.2 将数据录入和显示分开
//ex:带有rendererComponent方法的试算表
package org.stairwaybook.scells
import swing._
class Spreadsheet(val height:Int,val width:Int) extends ScrollPane{
	val cellModel=new Model(height,width)
	import cellModel._
	val table = new Table(height,width){
		override def rendererComponent(isSelected:Boolean,hasFocus:Boolean,row:Int,column:Int):Component=
			if (hasFocus) new TextField(userData(row,column))
			else new Label(cells(row)(column).toString){xAlignment=Alignment.Right}
		def userData(row:Int,column:Int):String={
			val v=this(row,column)
			if (v==null) "" else v.toString
		}
	}
}
//ex:Model类初稿
class Model(val height:Int,val width:Int){
	case class Cell(row:Int,column:Int)
	val cells=Array.ofDim[Cell](height,width)
	for(i<- 0 until height ;j<- 0 until width) cells(i)(j)=new Cell(i,j)
}


//35.3 公式
//ex:表示公式的类
trait Formula
//表示单元格坐标
case class Coord(row:Int,column:Int) extends Formula{override def toString=('A'+column).toChar.toString+row}
//表示单元格区间
case class Range(c1:Coord,c2:Coord) extends Formula{override def toString=c1.toString+c2.toString}
//表示浮点数
case class Number(value:Double) extends Formula{override def toString=value.toString}
//表示文本标签
case class Textual(value:String) extends Formula{override def toString=value}
//用于函数应用 例sum(A1,A2)
case class Application(function:String,arguments:List[Formula]) extends Formula{override def toString=function+arguments.mkString("(",",",")")}
object Empty extends Textual("")


//35.4 解析公式 P760
package org.stairwaybook.scells
import scala.util.parsing.combinator._
object FormulaParsers extends RegexParsers{
	def ident:Parser[String]="""[a-zA-Z_]\w*""".r
	def decimal:Parser[String]="""-?\d+(\.\d*)?""".r
	def cell:Parser[Coord]=
		"""[A-Za-z_]\d+""".r ^^ {s=>
			val column=s.charAt(0).toUpper - 'A'
			val row=s.substring(1).toInt
			Coord(row,column)
			}
	def range:Parser[Range]=cell~":"~cell ^^ {case c1~":"~c2=>Range(c1,c2)}
	def number:Parser[Number]=decimal ^^ (d=>Number(d.toDouble))
	def application:Parser[Application]=ident~"("~repsep(expr,",")~")" ^^ {case f~"("~ps~")" => Application(f,ps)}
	def expr:Parser[Formula]=range|cell|number|application
	def textual:Parser[Textual]="""[^=].*""".r ^^ Textual
	def formula:Parser[Formula]=number|textual| "="~>expr
	def parse(input:String):Formula=
		parseAll(formula,input) match {
			case Success(e,_) => e
			case f:NoSuccess => Textual("["+f.msg+"]")
		}
}

//ex:可以解析公式的试算表
package org.stairwaybook.scells
import swing._
import event._
class Spreadsheet(val height:Int,val width:Int) extends ScrollPane{
	val cellModel=new Model(height,width)
	import cellModel._
	val table = new Table(height,width){
		override def rendererComponent(isSelected:Boolean,hasFocus:Boolean,row:Int,column:Int):Component=
			if (hasFocus) new TextField(userData(row,column))
			else new Label(cells(row)(column).toString){xAlignment=Alignment.Right}
		def userData(row:Int,column:Int):String={
			val v=this(row,column)
			if (v==null) "" else v.toString
		}
		reactions+={ case TableUpdated(table,rows,column)=>for(row<-rows) cells(row)(column).formula=FormulaParsers.parse(userData(row,column))}
	}
}

//35.5 求值
//ex: Evatluator特质的evaluate方法
def evaluate(e:Formula):Double =try{
	e match {
		case Coord(row,column)=>cells(row)(column).value
		case Number(v)=>v
		case Textual(_)=>0
		case Application(function,arguments)=>
			val argvals=arguments flatMap evalList
			operations(function)(argvals)
		}
	} catch{case ex:Exception=>Double.NaN
type Op=List[Double]=>Double
val operations=new collection.mutable.HashMap[String,Op]
//evalList:求值函数
private def evalList(e:Formula):List[Double]=e match {
	case Range(_, _) => references(e) map (_.value)
	case _ =>List(evaluate(e))
}

//35.6 操作类库 P768
//ex:用于算术操作的类库
trait Arithmetic {this:Evaluator=>
	operations+=(
		"add" ->{case List(x,y)=>x+y},
		"sub" ->{case List(x,y)=>x-y},
		"div" ->{case List(x,y)=>x/y},
		"mul" ->{case List(x,y)=>x*y},
		"mod" ->{case List(x,y)=>x%y},
		"sum" ->{xs=>(0.0 /: xs)(_ + _)},
		"prod" ->{xs=>(1.0 /: xs)(_ * _)}
		)
}

//35.7 变更通知 P771
//ex: 试算表组件最终版
package org.stairwaybook.scells
import  swing._ , event._
class Spreadsheet(val height:Int,val width:Int) extends ScrollPane{
	val cellModel=new Model(height,width)
	import cellModel._
	val table = new Table(height,width){
		rowHeight=25
		autoResizeMode=Table.AutoResizeMode.Off
		showGrid=true
		gridColor=new java.awt.Color(150,150,150)
	}
	override def rendererComponent(isSelected:Boolean,hasFocus:Boolean,row:Int,column:Int):Component=
			if (hasFocus) new TextField(userData(row,column))
			else new Label(cells(row)(column).toString){xAlignment=Alignment.Right}
	def userData(row:Int,column:Int):String={
			val v=this(row,column)
			if (v==null) "" else v.toString
	}
	reactions += {
		case TableUpdated(table,rows,column)=>
			for (row<-rows) cells(row)(column).formula=FormulaParsers.parse(userData(row,column))
		case ValueChanged(cell)=>updateCell(cell.row,cell.column)}
	for (row<-cells;cell<-row) listenTo(cell)
	}
	val rowHeader=new ListView(0 until height){
		fixedCellWidth=30
		fixedCellHeight=table.rowHeight
	}
	viewportView=table
	rowHeaderView=rowHeader
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值