Skip to content

Commit 2cd962f

Browse files
committed
complete scala notes
1 parent 70dd10e commit 2cd962f

19 files changed

+3391
-1
lines changed

2013-12-20-scala-note5-class.md

+411
Large diffs are not rendered by default.

2013-12-21-scala-note6-enumeration.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## Scala笔记6-枚举
2+
3+
使用枚举
4+
5+
```scala
6+
object TrafficLightColor extends Enumeration {
7+
val Red, Yellow, Green = Value
8+
}
9+
```
10+
11+
可以指定ID和name:
12+
13+
```scala
14+
object TrafficLightColor extends Enumeration {
15+
val Red = Value(0, "Stop") // Red.toString() to get "Stop"
16+
val Yellow = Value(10) // Name "Yellow"
17+
val Green = Value("Go") // ID 11
18+
}
19+
```
20+
21+
枚举的类型是TrafficLightColor.Value 而不是 TrafficLightColor 可以增加一个`类型别名`:
22+
23+
```scala
24+
object TrafficLightColor extends Enumeration {
25+
type TrafficLightColor = Value
26+
val Red = Value(0, "Stop")
27+
val Yellow = Value(10)
28+
val Green = Value("Go")
29+
}
30+
31+
object Run extends App {
32+
import TrafficLightColor._
33+
def doWhat(color: TrafficLightColor) = {
34+
if (color == Red) "stop"
35+
else if (color == Yellow) "hurry up" else "go"
36+
}
37+
38+
// load Red
39+
TrafficLightColor(0) // Calls Enumeration.apply
40+
TrafficLightColor.withName("Red")
41+
}
42+
```

2013-12-22-scala-note7-file.md

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
## Scala笔记7-文件读写与序列化
2+
3+
读文件
4+
5+
```scala
6+
object Run extends App {
7+
import scala.io.Source
8+
val source = Source.fromFile("myfile.txt", "UTF-8")
9+
// The first argument can be a string or a java.io.File
10+
// You can omit the encoding if you know that the file uses the default platform encoding
11+
12+
for (c <- source) println(c) // c is a Char
13+
14+
val lineIterator = source.getLines
15+
for (l <- lineIterator) println(l) // l is a String
16+
17+
val lines = source.getLines.toArray // the whole content as an Array
18+
19+
val contents = source.mkString // the whole content as a String
20+
}
21+
```
22+
23+
缓存读,想查看某个字符,但不想一下子处理掉它
24+
25+
```scala
26+
object Run extends App {
27+
import scala.io.Source
28+
val source = Source.fromFile("myfile.txt", "UTF-8")
29+
30+
val iter = source.buffered
31+
while (iter.hasNext) {
32+
if (iter.head == 'B') println(iter.next)
33+
else iter.next
34+
}
35+
36+
source.close()
37+
}
38+
```
39+
40+
读文件并分成一个个单词,转换成数字
41+
42+
```scala
43+
object Run extends App {
44+
import scala.io.Source
45+
val source = Source.fromFile("myfile.txt", "UTF-8")
46+
47+
val tokens = source.mkString.split("\\s+")
48+
49+
val numbers = for (w <- tokens) yield w.toDouble
50+
val numbers2 = tokens.map(_.toDouble)
51+
}
52+
```
53+
54+
从控制台读取数字
55+
56+
```scala
57+
object Run extends App {
58+
print("How old are you? ")
59+
val age = readInt() // Or use readDouble or readLong
60+
}
61+
```
62+
63+
从其他源读取
64+
65+
```scala
66+
object Run extends App {
67+
import scala.io.Source
68+
val source1 = Source.fromURL("http://horstmann.com", "UTF-8")
69+
val source2 = Source.fromString("Hello, World!") // Reads from the given string—useful for debugging
70+
val source3 = Source.stdin // Reads from standard input
71+
}
72+
```
73+
74+
读取二进制文件
75+
76+
```scala
77+
import java.io.File
78+
import java.io.FileInputStream
79+
import scala.io.Source
80+
81+
object Run extends App {
82+
val file = new File("myfile")
83+
val in = new FileInputStream(file)
84+
val bytes = new Array[Byte](file.length.toInt)
85+
in.read(bytes)
86+
in.close()
87+
}
88+
```
89+
90+
写入文本文件
91+
92+
```scala
93+
import java.io.PrintWriter
94+
95+
object Run extends App {
96+
val out = new PrintWriter("numbers.txt")
97+
for (i <- 1 to 100) out.println(i)
98+
out.close()
99+
100+
// use string format
101+
val quantity = 100
102+
val price = .1
103+
out.print("%6d %10.2f".format(quantity, price))
104+
}
105+
```
106+
107+
访问目录
108+
109+
遍历所有子目录
110+
111+
```scala
112+
object Run extends App {
113+
import java.io.File
114+
def subdirs(dir: File): Iterator[File] = {
115+
val children = dir.listFiles.filter(_.isDirectory)
116+
children.toIterator ++ children.toIterator.flatMap(subdirs _)
117+
}
118+
}
119+
```
120+
121+
java.nio.file.Files类的walkFileTree方法
122+
123+
```scala
124+
object Run extends App {
125+
import java.nio.file._
126+
implicit def makeFileVisitor(f: (Path) => Unit) = new SimpleFileVisitor[Path] {
127+
override def visitFile(p: Path, attrs: attribute.BasicFileAttributes) = {
128+
f(p)
129+
FileVisitResult.CONTINUE
130+
}
131+
}
132+
133+
// Print all subdirectories with the call
134+
import java.io.File
135+
val dir:File = new File("/tmp")
136+
// public static Path walkFileTree(Path start, FileVisitor<? super Path> visitor)
137+
// Here implicit conversion adapts a function to the interface(FileVisitor)
138+
Files.walkFileTree(dir.toPath, (f: Path) => println(f))
139+
}
140+
```
141+
142+
序列化
143+
144+
```scala
145+
@SerialVersionUID(42L) class Person extends Serializable
146+
147+
object Run extends App {
148+
val fred = new Person
149+
import java.io._
150+
val out = new ObjectOutputStream(new FileOutputStream("/tmp/test.obj"))
151+
out.writeObject(fred)
152+
out.close()
153+
val in = new ObjectInputStream(new FileInputStream("/tmp/test.obj"))
154+
val savedFred = in.readObject().asInstanceOf[Person]
155+
}
156+
```

2013-12-23-scala-note8-process.md

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
## Scala笔记8-进程控制
2+
3+
sys.process包包含了一个从字符串到ProcessBuilder对象的隐式转换。!操作符执行的就是这个ProcessBuilder对象。
4+
5+
```scala
6+
object Run extends App {
7+
import sys.process._
8+
val result = "ls -al .." ! // result is 0 if command is done succeed
9+
10+
// pipe the output of one program into the input of another, using the #| operator
11+
"ls -al .." #| "grep z" !
12+
13+
// pipe the output of one program into the input of another, using the #| operator
14+
import java.io.File
15+
"ls -al .." #> new File("output.txt") !
16+
17+
// To append to a file, use #>> instead:
18+
"ls -al .." #>> new File("output.txt") !
19+
20+
// To redirect input from a file, use #<:
21+
"grep sec" #< new File("output.txt") !
22+
23+
// You can also redirect input from a URL:
24+
import java.net.URL
25+
"grep Scala" #< new URL("http://horstmann.com/index.html") !
26+
}
27+
```
28+
29+
如果需要在不同的目录下运行进程,或者使用不同的环境变量,用Process对象的apply方法来构造ProcessBuilder,给出命令和起始目录,以及一串(key, value)对来设置环境变量:
30+
31+
```scala
32+
import java.io.File
33+
34+
object Run extends App {
35+
import sys.process._
36+
val cmd = "ls -al"
37+
val dirName = "/tmp"
38+
val p = Process(cmd, new File(dirName), ("LANG", "en_US"))
39+
40+
"echo 42" #| p !
41+
}
42+
```
43+
44+
重定向标准输出和错误输出流:
45+
46+
```scala
47+
import sys.process._
48+
49+
object Run extends App {
50+
val logger = ProcessLogger(
51+
(o: String) => println("out " + o),
52+
(e: String) => println("err " + e))
53+
"ls -al" ! logger
54+
55+
val out = new StringBuilder
56+
val err = new StringBuilder
57+
val strlogger = ProcessLogger(
58+
(o: String) => out.append(o),
59+
(e: String) => err.append(e))
60+
"ls -al" ! strlogger
61+
}
62+
```

2013-12-24-scala-note9-regex.md

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
## Scala笔记9-正则表达式与文法解析
2+
### 正则表达式
3+
要构造一个Regex对象,用String类的r方法即可。如果正则表达式包含反斜杠或引号,最好使用"""...""":
4+
5+
```scala
6+
object Run extends App {
7+
val numPattern = "[0-9]+".r
8+
9+
val wsnumwsPattern = """\s+[0-9]+\s+""".r // use the “raw” string syntax
10+
11+
for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles"))
12+
println(matchString) // 99
13+
//98
14+
15+
val matches = numPattern.findAllIn("99 bottles, 98 bottles").toArray // Array(99, 98)
16+
17+
val m0 = numPattern.findFirstIn("99 bottles, 98 bottles") // Some(99)
18+
val m1 = wsnumwsPattern.findFirstIn("99 bottles, 98 bottles") // Some(98)
19+
20+
numPattern.findPrefixOf("99 bottles, 98 bottles") // Some(99)
21+
wsnumwsPattern.findPrefixOf("99 bottles, 98 bottles") // None
22+
23+
numPattern.replaceFirstIn("99 bottles, 98 bottles", "XX") // "XX bottles, 98 bottles"
24+
numPattern.replaceAllIn("99 bottles, 98 bottles", "XX") // "XX bottles, XX bottles"
25+
}
26+
```
27+
28+
### 正则表达式组
29+
在你想要提取的子表达式两侧加上圆括号:
30+
31+
```scala
32+
object Run extends App {
33+
val numitemPattern = "([0-9]+) ([a-z]+)".r
34+
35+
val numitemPattern(num, item) = "99 bottles" // Sets num to "99", item to "bottles"
36+
37+
for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 98 bottles"))
38+
printf("%d,%s\n", num.toInt, item) // 99,bottles
39+
//98,bottles
40+
}
41+
```
42+
43+
### 文法
44+
所谓`文法`(grammar),指的是一组用于产出所有遵循某个特定结构的字符串的规则。文法通常以一种被称为`巴斯克范式`(BNF)的表示法编写。
45+
46+
digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
47+
number::= digit | digit number
48+
op ::= "+" | "-" | "*"
49+
expr ::= number | expr op expr | "(" expr ")"
50+
51+
更高效的做法是在解析开始之前就收集好数字,这个单独的步骤叫做`词法分析`(lexical analysis)。`词法分析器`(lexer)会丢弃掉空白和注释并形成`词法单元`(token)——标识符、数字或符号。
52+
53+
在我们的表达式中,词法单元为number和符号+-*()。op和expr不是词法单元。它们是结构化的元素,是文法的作者创造出来的,目的是产出正确的词法单元序列。这样的符号被称为`非终结符号`。其中有个非终结符号位于层级的顶端,在我们的示例当中就是expr。这个非终结符号被称为`起始符号`,要产出正确格式的字符串,你应该从起始符号开始,持续应用文法规则,直到所有的非终结符号都被替换掉,只剩下词法单元:
54+
55+
expr -> expr op expr -> number op expr -> number "+" expr -> number "+" number
56+
57+
表明3+4是个合法的表达式。
58+
59+
最常用的“扩展巴斯克范式”,或称EBNF,允许给出可选元素和重复。将使用正则操作符?*+来分别表示0个或1个、0个或更多、1个或更多。
60+
61+
### 组合解析器操作
62+
为了使用scala解析库,我们需要提供一个扩展自Parsers特质的类并定义那些由基本操作组合起来的解析操作,基本操作包括:
63+
64+
* 匹配一个词法单元
65+
* 在两个操作之间做选择(|)
66+
* 依次执行两个操作(~)
67+
* 重复一个操作(rep)
68+
* 可选择地执行一个操作(opt)
69+
70+
```scala
71+
import scala.util.parsing.combinator.RegexParsers
72+
73+
class ExprParser extends RegexParsers {
74+
val number = "[0-9]".r
75+
76+
def expr: Parser[Any] = term ~ opt(("+" | "-") ~ expr)
77+
def term: Parser[Any] = factor ~ rep("*" ~ factor)
78+
def factor: Parser[Any] = number | "(" ~ expr ~ ")"
79+
}
80+
81+
object Main extends App {
82+
val parser = new ExprParser
83+
val result = parser.parseAll(parser.expr, "3-4*5")
84+
if (result.successful) println(result.get)
85+
}
86+
```
87+
88+
上述程序的输出`((3~List())~Some((-~((4~List((*~5)))~None))))`,解读这个结果:
89+
90+
* 字符串字面量和正则表达式返回String值
91+
* p ~ q返回~样例类的一个实例
92+
* opt(p)返回一个Option,要么是Some(...),要么是None
93+
* rep(p)返回一个List
94+
95+
### 解析器结果变换
96+
与其让解析器构建出一整套由~、可选项和列表构成的复杂结构,不如将中间输出变换成有用的形式。
97+
98+
```scala
99+
import scala.util.parsing.combinator.RegexParsers
100+
101+
class ExprParser extends RegexParsers {
102+
val number = "[0-9]".r
103+
104+
def expr: Parser[Int] = term ~ opt(("+" | "-") ~ expr) ^^ {
105+
case t ~ None => t
106+
case t ~ Some("+" ~ e) => t + e
107+
case t ~ Some("-" ~ e) => t - e
108+
}
109+
def term: Parser[Int] = factor ~ rep("*" ~ factor) ^^ {
110+
case f ~ r => f * r.map(_._2).product
111+
}
112+
def factor: Parser[Int] = number ^^ {_.toInt}| "(" ~ expr ~ ")" ^^ {
113+
case _ ~ e ~ _ => e
114+
}
115+
}
116+
117+
object Main extends App {
118+
val parser = new ExprParser
119+
val result = parser.parseAll(parser.expr, "3-4*5")
120+
if (result.successful) println(result.get) //-17
121+
}
122+
```
123+
124+
* ^^符号并没有什么特别的意义,它只是恰巧比~优先级低,但又比|优先级高
125+
* 对于解析来说,词法单元是必须的,但在匹配之后它们通常可以被丢弃。~>和<~操作符可以用来匹配并丢弃词法单元。
126+
127+
```scala
128+
def term: Parser[Int] = factor ~ rep("*" ~> factor) ^^ {
129+
case f ~ r => f * r.product
130+
}
131+
132+
def factor: Parser[Int] = number ^^ {_.toInt}| "(" ~> expr <~ ")"
133+
```

0 commit comments

Comments
 (0)