Scala学习笔记

阅读更多
一、变量:
  val v1 = 2;//变量,不能重新赋值,函数式语言大量提倡使用val变量,Erlang所有的变量都是val的
  var v2 = 3;//变量,和Java的变量一致
  def v3 = v1 * v2;//只是定义v1*v2表达式的名字,并不求值,在使用的求值

lazy val lazyVal = { println("I'm too lazy"); 1 }
println("after lazyVal")
val x = lazyVal

打印出:
after lazyVal
I'm too lazy
二、表达式:
For comprehensioon
val dogBreeds = List("Doberman", "Yorkshire Terrier", "Dachshund",
"Scottish Terrier", "Great Dane", "Portuguese Water Dog")
for (breed <- dogBreeds)
	println(breed)
for(bread <- dogBreads
    if bread.contains("Terrier");
    if !bread.contains("Yorkshire");
)println(bread)

//yield
val filteredBreeds = for {
   breed <- dogBreeds
   if breed.contains("Terrier")
   if !breed.startsWith("Yorkshire")
} yield breed

避免使用显式返回

三、条件控制:
while,do...while没有什么特别
if...else
for 表达式:
val filesHere = (new java.io.File(".")).listFiles
for (file <- filesHere)
     println(file)
for(i <- 1 to 4){//和Ruby中的1..4一样
   println(i)
}
for(i <-1 util 4){//和Ruby中的1...4一样
   println(i)
}

一切表达式都有返回值,条件控制语句也不例外
val v1 = if(true) 1 else 0

四、函数式编程:
1、一切操作都是函数调用:
1 + 1 等价于 1.+(1)
for (i <- List(1, 2)) {
println(i)
}
//for是函数调用

2、一切函数都可以作为操作符使用:
1 max 2
3、函数嵌套:
def sqrt(x: Double) = {
	def sqrtIter(guess: Double, x: Double): Double =
		if (isGoodEnough(guess, x)) guess
		else sqrtIter(improve(guess, x), x)
	def improve(guess: Double, x: Double) =
		(guess + x / guess) / 2
	def isGoodEnough(guess: Double, x: Double) =
		abs(square(guess) x) < 0.001
	sqrtIter(1.0, x)
}


4、函数是一等公民:
(x: Int) => x + 1//匿名函数
var inc = (x: Int) => x + 1//赋值给一个变量
inc(10)


val someNumbers = List(-11,-10,-5,0, 5, 10)
someNumbers.foreach((x: Int) => println(x))
someNumbers.filter((x: Int) => x > 0)

利用类型推到简化:
 someNumbers.foreach(x => println(x))

使用占位符语法(Placeholder syntax)
someNumbers.filter(_ > 0)

使用Partially applied functions
someNumbers.foreach( println _ )

由于foreach期望一个函数作为参数,所以可以简化为
someNumbers.foreach(println)

5、闭包:
var more = 1
var addMore = (x: Int) => x + more
addMore(10)

结果是11
闭包绑定的是定义时的变量,而不是值
var more = 2
addMore(10)

结果是12
6、尾递归:
递归函数在最后一个操作调用自身
def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)

7、偏函数(Partial Function)
def concatUpper(s1: String, s2: String): String = (s1 + " " + s2).toUpperCase
val c = concatUpper("hello,",_:String)
c("world")

偏函数的类型是PartialFunction,他是一个trait,定义了一个函数orElse
val truthier: PartialFunction[Boolean, String] = { case true => "truthful" }
val fallback: PartialFunction[Boolean, String] = { case x => "sketchy" }
val tester = truthier orElse fallback
println(tester(1 == 1))
println(tester(2 + 2 == 5))


8、curry化:
def cat(s1: String)(s2: String) = s1 + s2
val c1 = cat("hello,")
c1("world)


普通函数可以转化成curry化的:
   def cat(s1: String)(s2: String) = s1 + s2
   var carryCat = Function.curried(cat _)
   cat("hello,")("world")

9、隐式转换:
Scala有一些常用的类型都有一个RichXxx类型:
4 max 3 就是自动转化成为 RichInt类型
val name: String = "scala"
println(name.capitalize.reverse)

java.lang.String中没有capitalize和reverse,通过
隐式转换成RichString来实现的,Predef里面定义了
implicit def stringWrapper(x: String) = new runtime.RichString(x)
隐式转换函数都用implicit修饰。
10、隐式函数参数(Implicit Function Parameters):
隐式参参数可以在上下文中找到并绑定到同名的变量:
def multiplier(i: Int)(implicit factor: Int) {
    println(i * factor)
}
implicit val factor = 2
multiplier(2)
multiplier(2)(3)

11、call-by-value or call-by-name
def f(x: Int) = x//call-by-value 
def f(x: => Int) = x//call-by-name(参数类型前面带有=>)
//使用call-by-name构建自己的流程控制语句
def myWhile(conditional: => boolean)(f: => Unit){
	if(conditional)
		f
         myWhile(conditional)(f)
}
var count = 0
myWhile( count < 5){
	println("still loop while");
        count += 1
}	

12、模式匹配:
函数式语言最重要的概念模式匹配:
匹配常量:
def fib(in: Int): Int = in match{
	case n if n <= 0 => 0
	case 1 => 1
        case n => fib2(n-1) + fib2(n-2)
}

可以匹配任何类型:
def activity(day: String){
  day match{
      case "Sunday" => print("Eat, sleep,repeat...")
      case "Saturday" => print("Hangout with friends...")
      case "Monday" => println("...code for fun...")			
  }
}

常量匹配和Java的switch...case类似,变量匹配使得变量得副作用而得到匹配的值。
元组匹配:
def coordinates(intput: Any){
  input match{
  	case (x,y) => printf("x=%d,y=%d",x,y);
        case _ => Nothing
  }
}

List匹配:
def sumOdd(in: List[Int]): Int in match{
	case Nil => 0
	case x::rest if x % 2 == 1 => x + sumOdd(rest)
        case _::rest => sumOdd(rest)
}

类型匹配:
def typeMatch(in: Any) = in match{
    case s: String => "String, length " + s.length
    case i: Int if i > 0 => "Natural Int"
    case i: Int => "Another Int"
    case a: AnyRef => a.getClass.getName
    case _ => "null"
}

类似于java的instanceof

case class:
case class Person(name: String,age:Int)
val p = Person("Smith" 20)

equals,hashcode,accessor all ok

case class匹配:
  case class Apple()
  case class Orange()
  case class Book()

  def accept(thing: Any){
     thing match{
       case Apple() => println("Apple")
       case Orangle() => println("Orange")
       case Book() => println("Book")
       case _ => println("Not accepted")
     }
  }

Sealed class:
匹配的case class是无法穷举的,Sealed class只能在和他相同的文件中定义子类,所以只需要关注
当前文件的case class匹配的列举,并且如果列举不全则编译时有Warning。
 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

 def describe(e: Expr): String = e match{
   case Number(x) => "a number"
   case Var(_) => "a variable"
 }

编译的时候会有Waring:
warning: match is not exhaustive!
missing combination           UnOp
missing combination          BinOp

正则表达式作为Extractor
def process(input: String){
   val MatchStock = """^(.+):(\d*\.\d+)""".r
    input match{
      case MatchStock("GooG", price) => println("Price Of GooG is " + price)
      case MatchStock("IBM",price) => println("Price of IBM is " + price)
      case _ => println("No data for access")
    }
}
prcoess("GooG:310.84")

13、Stream:

五、面向对象:
1、一切皆是对象
//值也是对象
123.toByte
true.toString
val compare = (x: Int, y: Int) = x > y//函数也是值

2、单例对象:
object Singleton{
	val v = 1;
}

main函数都是写在伴生对象中的
3、没有静态成员:
以为他们的实例也必须是对象的实例
object Dog {
   val whatever = "dog" // static field in Java
}

4、主构造函数:
class Rational(n: Int,d: Int){//主构造函数
    def this(n: Int) = this(n,1)////Auxiliary constructors
}

5、访问子:
没有声明为private的字段自动生成getter,setter方法:
class Time {
 var hour = 12
 var minute = 0
}

等价于:
class Time {
   private[this] var h = 12
   private[this] var m = 0
   def hour: Int = h
   def hour_=(x: Int) { h = x }
   def minute = m
   def minute_=(x: Int) { m = x }
}

6、覆写override:
覆写关键词是必须的(抽象的是可选的),而不像java的@override是可选的:
class Rational(n: Int, d: Int) extends AnyRef {
  //...other code 
  override def toString = "" + numer + "/" + denom
}

不光可以覆写函数,还可以覆写字段
class AbstractParent {
  def name = "parent";
}
class ConcreteChild extends AbstractParent {
  override val name = "Child"
}


6、伴生对象:
和类名一样的单例对象成为伴生对象。
在伴生对象中的类和Java的静态成员类似。


7、抽象类型:
类、方法、字段和类型都可以为抽象的。
abstract class AbstractParent {//抽象类
	def name: String//抽象字段
}
class ConcreteChild extends AbstractParent {
	val name = "Child"//覆写集成的字段,由于父类是抽象的,所以可以省略override字段
}
println(new ConcreteChild().name)

8、方法和字段不可以重名:
方法和字段被设置为统一命名空间。无参方法可以省略括号。
7、操作符重载

scala允许操作符作为函数名,使用重载和定义普通的函数类似。
def +()
重载+隐式转换经常一起使用
比c++简单:c++使用operator()+ 和使用operator()进行重载和类型隐式转换,并且
区分为成员还是友元重载。
待补充....
六、类型体系:
待补充...
七、DSL
待补充...
八、Actor

你可能感兴趣的:(Scala,Java,正则表达式,REST,Apple)