Scala的基本概念
先讲讲Scala里头几个概念Classes, Traits, Objects and Packages。
Class和Java中的很像,只不过Scala中Class不能有static members。还有个叫做case的特殊类。
Object跟Class也很像,只不过它只能有一个instance,它可以有 static members。
Traits跟Java中的Interface很像,不过它可以有concrete members, i.e. method implementations or field definitions
Packages跟Java中的也很像。不只是类型可以被import。for instance if you have an object baz in package foo.bar, then import foo.bar.baz._ would import all the members of that object.
想要快速看懂Scala的奇葩代码的话十二步学会Scala这篇日志不错,可以在simplyscala上小试牛刀,progfun课程也有个Cheatsheet。
我来说说里面比较好(keng)玩(die)的几个例子,你们随意感受一下
1 神奇的替代符_
scala> def max(x: Int, y: Int): Int = if(x < y) y else x
max: (x: Int, y: Int)Int
scala> val m = max _
m: (Int, Int) => Int = <function2>
scala> m(1,2)
res0: Int = 2
scala> val m = max(1:Int, _:Int)
m: Int => Int = <function1>
scala> m(-1)
res3: Int = 1
2 特别的括号<>[]()用法
scala> val str = new Array[String](3)
str: Array[String] = Array(null, null, null)
scala> str(0) = "hello"
scala> str(1) = ","
scala> str(2) = "world"
3 foreach和for循环,还有奇妙的apply语法糖
scala> str.foreach(s=>print(s))
hello,world
scala> str.foreach(print)
hello,world
scala> for(s <- str)
| print(s)
hello,world
scala> for(i <- 0.to(2))
| print(str.apply(i))
hello,world
scala> for(i <- 0 to 2)
| print(str apply i)
hello,world
4 foreach:没有返回值的map
collect:可以只返回部分元素处理结果的map
scala> val mixedList = List("a", 1, 2, "b", 19, 42.0)
mixedList: List[Any] = List(a, 1, 2, b, 19, 42.0)
scala> mixedList.map{
| case i: Int => "Int:" + i.toString
| case s: String => "String:" + s
| case _ => ""
| }
res20: List[java.lang.String] = List(String:a, Int:1, Int:2, String:b, Int:19, "")
scala> mixedList.foreach{
| case s: String => "String:" + s
| case i: Int => "Int:" + i.toString
| case _ => ""
| }
//没有返回值
scala> mixedList.collect{
| case i: Int => "Int:" + i.toString
| case s: String => "String:" + s
| }
res22: List[java.lang.String] = List(String:a, Int:1, Int:2, String:b, Int:19)
5 reduce、foldLeft/foldRight和scanLeft/scanRight
scala> val input = List(3, 5, 7, 11)
input: List[Int] = List(3, 5, 7, 11)
scala> input.foldLeft(0)(_+_)
res35: Int = 26
scala> input.reduce(_+_)
res36: Int = 26
scala> input.scanLeft(0)(_+_)
res0: List[Int] = List(0, 3, 8, 15, 26)
scala> input.scanRight(0)(_+_)
res1: List[Int] = List(26, 23, 18, 11, 0)
6 filter
scala> def isEven(i: Int): Boolean = i % 2 == 0
isEven: (i: Int)Boolean
scala> numbers.filter(isEven _)
res2: List[Int] = List(2, 4)
8 flatMap:先map再flatten
scala> val lstw=List("Once","more","unto","the","breach")
lstw: List[java.lang.String] = List(Once, more, unto, the, breach)
scala> lstw.flatMap(_.toList)
res9: List[Char] = List(O, n, c, e, m, o, r, e, u, n, t, o, t, h, e, b, r, e, a, c, h)
scala> lstw.map(_.toList)
res15: List[List[Char]] = List(List(O, n, c, e), List(m, o, r, e), List(u, n, t, o), List(t, h, e), List(b, r, e, a, c, h))
scala> lstw.map(_.toList).flatten
res17: List[Char] = List(O, n, c, e, m, o, r, e, u, n, t, o, t, h, e, b, r, e, a, c, h)
9 用case class处理Map的元素
scala> val extensions = Map("steve" -> 100, "bob" -> 101, "joe" -> 201)
extensions: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 100, bob -> 101, joe -> 201)
scala> extensions.filter({case (name,ext) => ext<200})
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 100, bob -> 101)
scala> extensions.filter({namePhone:(String, Int) => namePhone._2<200})
res1: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 100, bob -> 101)
10 特别的数据类型 Option[T],Some[T],None
scala> numbers.getOrElse(9,-1)
res4: Any = -1
scala> numbers.get(9).getOrElse(-1)
res5: Any = -1
scala> numbers.get(9) match{
| case Some(n)=>n
| case None => -1
| }
res6: Any = -1
11 val, lazy, def的区别
举个栗子:
1 |
val strVal = scala.io.Source.fromFile( "test.txt" ).mkString //在strVal被定义的时候获取值,如果test.txt不存在,直接报异常
|
2 |
3 |
lazy val strLazy = scala.io.Source.fromFile( "test.txt" ).mkString //在strLazy第一次被使用的时候取值,如果test.txt不存在,不使用strLazy是不会报异常的,第一次访问strLazy的时候报异常
|
4 |
5 |
def strDef = scala.io.Source.fromFile( "test.txt" ).mkString //每次使用的时候都重新取值<span></span>
|
如果一开始test.txt内容是"a",定义好之后,将test.txt内容改为"ab",则strVal == "a", strLazy == "ab",strDef == "ab"。
再将test.txt内容改为"abc",则strVal == "a", strLazy == "ab",strDef == "abc"。再修改test.txt的内容,strVal和strLazy都不会改变,而strDef每次都更新。
12 正则表达式
在Scala中,java.lang.String里丰富的字符串处理库是可以直接用哒,你可以这样
str match{
case s if s.startsWith("!!!")=> s.stripPrefix("!!!")
case _ =>
}
不过如果你愿意,也可以这样
val r ="""^!!!(.*)""".r
val r(suffix)="!!!rest of string"
So suffix
will be populated with rest of string, or a scala.MatchError
gets thrown.
A different variant would be:
val r ="""^(!!!){0,1}(.*)""".r
val r(prefix,suffix)=...
And prefix
will either match the !!! or be null. e.g.
(prefix, suffix) match{
case(null, s)=>"No prefix"
case _ =>"Prefix"
}
13.Dynamic(虽然我觉得这个其妙的功能其实没啥用啊)
14.Reflection和Macro
Environment, Universes, and Mirrors
最后谈下函数式数据结构:
函数式编程一个很大的特点就是方法不产生副作用(side effects),就是这个方法不改变任何东西。参数传进去,经过加工输出这个过程中没有任何变量被改变。像Java的String就是一个例子,是不可更改,它里面所有的方法都不会把对象里面任何东西做更改。
上述数组str定义为val变量,定义了类型和容量,那么这个变量的类型和容量就不能修改了。但他里面的元素还是可以重新赋值,产生了副作用,因此Array不是纯函数式的类。
但是Scala的List和Tuple是函数式的,也就是一次定型,不可修改。
关于Scala,Coursera开了课,可以看看配环境之类的
https://class.coursera.org/progfun-003
学语法还是自己看文字比较快
http://twitter.github.io/scala_school/zh_cn
http://www.ibm.com/developerworks/cn/java/j-scala
http://www.ibm.com/developerworks/cn/java/j-lo-funinscala2
http://zh.scala-tour.com/#/welcome
API文档里头都没有demo,不太友好
http://scalachina.com/api/index.html#package
常用的数据结构不妨看文档
http://docs.scala-lang.org/overviews/collections/sets.html
http://docs.scala-lang.org/overviews/core/string-interpolation.html
http://docs.scala-lang.org/cheatsheets
http://docs.scala-lang.org/tutorials
http://docs.scala-lang.org/tutorials/scala-for-java-programmers.html
http://www.scala-lang.org/documentation/
基础打好后,就要有更高的追求啦,Effective Scala欢迎你
参考: