Scala学习笔记

xiaoxiao2021-03-01  13

一、变量: [code] val v1 = 2;//变量,不能重新赋值,函数式语言大量提倡使用val变量,Erlang所有的变量都是val的 var v2 = 3;//变量,和Java的变量一致 def v3 = v1 * v2;//只是定义v1*v2表达式的名字,并不求值,在使用的求值 [/code] [code] lazy val lazyVal = { println("I'm too lazy"); 1 } println("after lazyVal") val x = lazyVal [/code] 打印出: 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)//yieldval 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(".")).listFilesfor (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) [code] val someNumbers = List(-11,-10,-5,0, 5, 10) someNumbers.foreach((x: Int) => println(x)) someNumbers.filter((x: Int) => x > 0) [/code] 利用类型推到简化: someNumbers.foreach(x => println(x)) 使用占位符语法(Placeholder syntax) [code] someNumbers.filter(_ > 0) [/code] 使用Partially applied functions [code] someNumbers.foreach( println _ ) [/code] 由于foreach期望一个函数作为参数,所以可以简化为 [code] someNumbers.foreach(println) [/code] 5、闭包: var more = 1var addMore = (x: Int) => x + moreaddMore(10) 结果是11 闭包绑定的是定义时的变量,而不是值 [code] var more = 2 addMore(10) [/code] 结果是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).toUpperCaseval c = concatUpper("hello,",_:String)c("world") 偏函数的类型是PartialFunction,他是一个trait,定义了一个函数orElse [code] 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)) [/code] 8、curry化: def cat(s1: String)(s2: String) = s1 + s2val c1 = cat("hello,")c1("world) 普通函数可以转化成curry化的: [code] def cat(s1: String)(s2: String) = s1 + s2 var carryCat = Function.curried(cat _) cat("hello,")("world") [/code] 9、隐式转换: Scala有一些常用的类型都有一个RichXxx类型: 4 max 3 就是自动转化成为 RichInt类型 [code] val name: String = "scala" println(name.capitalize.reverse) [/code] 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 = 2multiplier(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 = 0myWhile( count < 5){ println("still loop while"); count += 1} 12、模式匹配: 函数式语言最重要的概念模式匹配: 匹配常量: [code] def fib(in: Int): Int = in match{ case n if n <= 0 => 0 case 1 => 1 case n => fib2(n-1) + fib2(n-2) } [/code] 可以匹配任何类型: [code] def activity(day: String){ day match{ case "Sunday" => print("Eat, sleep,repeat...") case "Saturday" => print("Hangout with friends...") case "Monday" => println("...code for fun...") } } [/code] 常量匹配和Java的switch...case类似,变量匹配使得变量得副作用而得到匹配的值。 元组匹配: [code] def coordinates(intput: Any){ input match{ case (x,y) => printf("x=%d,y=%d",x,y); case _ => Nothing } } [/code] List匹配: [code] 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) } [/code] 类型匹配: [code] 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" } [/code] 类似于java的instanceof case class: [code] case class Person(name: String,age:Int) val p = Person("Smith" 20) [/code] equals,hashcode,accessor all ok case class匹配: [code] 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") } } [/code] Sealed class: 匹配的case class是无法穷举的,Sealed class只能在和他相同的文件中定义子类,所以只需要关注 当前文件的case class匹配的列举,并且如果列举不全则编译时有Warning。 [code] 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" } [/code] 编译的时候会有Waring: warning: match is not exhaustive! missing combination UnOp missing combination BinOp 正则表达式作为Extractor [code] 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") [/code] 13、Stream: 五、面向对象: 1、一切皆是对象 //值也是对象 123.toBytetrue.toStringval 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 相关资源:微信小程序源码-合集1.rar
转载请注明原文地址: https://www.6miu.com/read-3450043.html

最新回复(0)