Scala for the Impatient - (Chapter 1, 2)
2013-08-26 13:57
330 查看
Declaring values and variables
scala推荐使用val声明变量,除非你需要修改变量内容才使用varscala中变量的类型要写在变量名后,根据stackoverflow上众位大神的解释,好处如下:
名称比类型更重要,这样做可以突出强调变量本身,而不是变量的类型。在scala中,类型推断应该交给编译器完成,写代码的人更应该关注如何使用
代码写起来更整洁,比如很多行由val,var,def开头的变量声明
使用diff来比较的时候,可以很清楚的看到某个变量的类型变化
Java中的Primitive Types都被重新定义成Class实现,要多多注意这些类的使用方法
Integer - RichInt
Double - RichDouble
Char - RichChar
String - StringOps
Arithmetic and Operator Overloading
Operator实际上都是类的各种方法,比如这个加法a + b a.+(b)
注意++操作符是不存在的
Calling Functions and Methods
比如Java中的Math.abs(a), method必须得跟在一个类的后面。到了scala,方法是可以脱离类存在的,就好像其他语言中的build-in functions一样,比如import scala.math._ sqrt(20) pow(2, 4) min(3, Pi)
scala中没有static method的说法,但是它提供了一种叫singleton objects的类似功能,即class可以有一个companion object来提供static methods (具体的用法后面解释)
如果是没有参数的method,写的时候就不要加括号了,啰嗦。一般的,如果该方法不会对象,那也可以不写括号。
The apply Method
没太看懂这段的介绍,stackoverflow上一个解释Conditional Expressions
scala中的if/else语句是有返回值的,比如下面这个例子。很明显,scala的写法要更加简洁,// scala val s = if (x>0) 1 else -1 // java int s; if (x>0) { s = 1; } else { s = -1; }
scala中每个表达式实际上都有一个类型,就是它的返回类型。
如果是if/else这种可能使用mixed-type,返回的就是它们的supertype。
val s = if (x>0) "possible" else -1 // s is Any
如果只是if,
val s = if (x>0) "possible" // equals: if (x>0) "possible" else () // () is Unit, ()可以看作是占位符, Unit就是void
Statement Termination
scala中默认不写分号,除非一行有多条语句,很好的语法特性Block Expressions and Assignments
跟Java一样,{ }包围着的就是一个Block,最后一句就是整个Block的值 (赋值语句的没有返回值,或者说返回的是Unit)Input and Output
print:print("Answer is ") println("Answer is ") printf("Anser is %s, with %d", "fred", 42)
read:
val name = readLine("Your name: ") val age = readInt() val salary = readDouble() // readInt, readDouble, readByte, readShort, readLong, readFloat, readBoolean, readChar
Loops
while, do-while都和java的用法一样for的变化很大,实际上for并不常用
for (i <- expr) // 意思是i将遍历右侧表达式中的每一个值
Advanced for Loops and for Comprehensions
一些基本的写法for (i <- 1 to 3; j <- 1 to 3) print((10*i + j) + " ") // 11, 12, 13, 21, 22, 23, 31, 32, 33 for (i <- 1 to 3; j <- 1 to 3 if i != j) print((10*i + j) + " ") // 12, 13, 21, 23, 31, 32 for (i <- 1 to 3; from = 4 - i; j <- from to 3) print((10*i + j) + " ") // 13, 22, 23, 31, 32, 33
stackoverflow上关于for comprehension的讨论
for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar // String: HIeflmlmop for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar // Char array: ['H', 'I', 'e', 'f', 'l', 'm', 'l', 'm', 'o', 'p']
Functions
scala中的Function可以独立于class存在def abs(x: Double) = if (x > 0) x else -x
除非是递归,否则不需要指定Function的返回值,编译器会自动推断返回值的类型
Default and Named Arguments
scala中,你可以为函数参数指定默认值def decorate(str: String, left: String = "[", right: String = "]") = left + str + right
调用函数的时候,也可以不按参数顺序,只要提供名称就好
decorate(left = ">>>", str = "wrap me", right = "<<<") // >>>wrap me<<<
Variable Arguments
// 此时的参数类型是Seq def sum(args: Int*) = { var result = 0 for (arg <- args) result += arg result }
如果你有了一个Sequence,你需要告诉编译器你希望传入的时候作为sequence来处理:
val s = sum(1 to 5: _*)
更加FP的sum实现:
def sum(args: Int*) : Int = { if (args.length == 0) return 0 else args.head += sum(args.tail: _*) } // args.head is initial element // args.tail is a sequence of all other elements
Procedues
没有返回值 (或者说返回值是Unit) 的Function,就叫做Procedue// 定义的时候不需要 = def box(s: String) { println("|" + s + "|\n") } // 或者 def box(s: String) : Unit = { println("|" + s + "|\n") }
Lazy Values
只要变量声明时候加了lazy,你不用就不会被初始化lazy val words = scala.io.Source.fromFile("/tmp/non-existed.log").mkString // 编译没问题。运行时,除非有代码调用到了words,否则不会去检查这个文件读取的时候有没有问题
val, lazy and def
val words = scala.io.Source.fromFile("/tmp/my.log").mkString // Evaluated as soon as words is defined lazy val words = scala.io.Source.fromFile("/tmp/my.log").mkString // Evaluated the first time words is used def words = scala.io.Source.fromFile("/tmp/my.log").mkString // Evaluated every time words is used
Exceptions
scala中没有checked exception, 意味着写代码的时候不需要声明一堆throw AAAException, BBBException.在try-catch中,异常捕捉是基于pattern-matching的,跟java相比显得格外简洁
try { process(new URL("http://www.example.com/test.gif")) } catch { case _: MailFormedURLException => println("Bad URL: " + url) case ex: IOException => ex.printStackTrace() } // use _ for the variable name if you don't need it
在try-finally中,finally跟java一样,无论如何都会被执行的
in = new URL("http://www.example.com/test.gif").openStream() try { process(in) } finally { in.close() }
相关文章推荐
- Scala for the Impatient课后练习(第1章 The Basics)
- scala 学习笔记(scala for the impatient)
- Scala for Impatient - Chapter 3
- 《快学Scala》, <Scala For the Impatient>习题第二章
- 《快学Scala》, <Scala For the Impatient>习题第三章
- Scala for the Impatients---(8)Inheritance
- Scala for the Impatients---(9)Files and Regular Expressions
- Boost.Interprocess使用手册翻译之二:快速指南 (Quick Guide for the Impatient)
- How do I iterate over a Scala List (or more generally, a sequence) using theforeach method or for loop?
- Open Source Big Data for the Impatient, Part 1
- Scala for the Impatients---(3)Working with Arrays
- Boost.Interprocess使用手册翻译之二:快速指南 (Quick Guide for the Impatient)
- Vegas--the missing matplotlib for scala
- Scala for the Impatients---(6)Objects
- [Learning You a Haskell for Great Goods!] chapter 02 believe the type
- JVM Specification 9th Edition (4) Chapter 3. Compiling for the Java Virtual Machine
- Boost.Interprocess使用手册翻译之二:快速指南 (Quick Guide for the Impatient)
- Scala for the Impatients---(1)Basics
- Scala for the Impatients---(4)Maps and Tuples
- Chapter 7Iterators and the Generic for