• Scalable 编程语言
  • 纯正的的面向对象语言
  • 函数式编程语言
  • 无缝的java互操作

scala之父 Martin Odersky

1. 函数式编程

  • 函数式编程(functional programming) 或称函数程序设计,又称泛函编程,是一种编程范型
  • 它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。
  • 函数编程语言最重要的基础是λ演算(lambda calculus), 而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。
  • 函数式编程强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。

1.1 函数式编程的重要概念

使用纯函数编程, 纯函数是没有副作用的函数

1.副作用

所谓"副作用"(side effect),指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。

函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。

  1. var x = 1
  2. def XplusY_v1(y: Int) = x+y
  3. def XplusY_v2(y: Int) = {x = x+y; x}

这里 XplusY_v2对 x 就有副作用, 函数执行之后 x 的状态会发生变化

而 XplusY_v1 执行之后不会改变 x 的值, XplusY_v1是纯函数

2.引用透明性

定义: 如果f(x)的参数和函数体都是引用透明的, 那么函数f是纯函数

特点: 对于相同的输入, 总是得到相同的输出.就是说,表达式的值不依赖于值可以改变的全局状态。

  1. var x = new StringBuild("Hello")
  2. var y = x.append("world")
  3. var z = x.append("world")

上面形同的表达式x.append("world")得到的结果不同, 由于x是一个值可以改变的变量

3.不变性(Immutablity)

为了获得透明性, 任何值都不能改变

4.函数是一等公民

(First-class Function)

函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

5.只有表达式

一切都是计算, 函数式编程中只有表达式, 变量, 函数都是表达式

"表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。也就是说,每一步都是单纯的运算,而且都有返回值。

6.闭包和高阶函数

函数编程支持函数作为第一类对象,有时称为 闭包或者 仿函数(functor)对象。实质上,闭包是起函数的作用并可以像对象一样操作的对象。

高阶函数(Higher order Function)可以用另一个函数(间接地,用一个表达式) 作为其输入参数,在某些情况下,它甚至返回一个函数作为其输出参数。

7.表达式求值策略

  • 严格求值
  • 非严格求值
  • 惰性求值

8.递归函数

递归实现循环: 尾递归

1.2 函数式编程的优势

  • 生产效率高
  • 易于推理
  • 并行计算
  • 多核计算

2. MacOS安装scala开发环境

3步走:

  1. 安装scala

    brew install scala
  2. 安装sbt

    brew install sbt
  3. Intellj IDEA上scala ,sbt插件下载

3. Scala 类型体系

4. Scala求值策略

Scala有两种求值策略

- Call By Value 对函数实参求值,且只求一次,如果作为参数值需要对表达式先进行求值

- Call By Name 对函数实参每次在函数体内被调用时都会求值

通常使用Call By Value

如果函数形参以 => 开头,那么会使用Call By Name

def foo(x: Int) = x // call by value

def foo(x: => Int) = x //call by name

例子

  1. def test1(x: Int, y: Int): Int = x * x
  2. def test2(x: => Int, y: => Int): Int = x * x
  3. 计算过程:
  4. test1(3+4, 8) | test2(3+4, 8) | test1(7, 2 *4) | test2(7, 2 *4)
  5. test1(7, 8) | (3+4)*(3+4) | test1(7, 8) | 7*7
  6. 7*7 | 7*(3+4) | 7*7 | 49
  7. 49 | 7*7 | 49 |
  8. | 49 | |
  1. def bar1(x: Int, y: =>Int) = 1
  2. def bar2(x: => Int, y: =>Int) = 1
  3. def loop(): Int = loop
  4. bar1(loop, 1) 死循环, 这里实参一直带求值loop, 一直没法拿到值
  5. bar2(loop, 1) 表达式值为1

5. Scala函数

scala中函数是第一等公民:

  1. 把函数作为实参传给另一个函数
  2. 把函数作为返回值
  3. 把函数赋值给变量
  4. 把函数存储在数据结构中

在Scala中函数和普通变量一样, 同样也具有函数类型

5.1 函数类型

在Scala中, 函数类型格式为 A => B

表示一个接受类型A的参数, 并返回类型B的参数, 如 Int => String

5.2 高阶函数

用函数作为形参或者返回值的函数, 称为高阶函数

  1. def operate(f: (int, int) => Int) = {
  2. f(4, 4)
  3. }
  4. def greeting() = (name: String) => {"hello" + " " + name} // 匿名函数

5.3 匿名函数

匿名函数就是函数常量, 也称为函数文字量

scala中匿名函数的格式为:

(形参列表) => (函数体)

  1. scala> (x: Int, y: Int) => x+y
  2. res2: (Int, Int) => Int = $$Lambda$1209/886693791@35c8be21
  3. scala> res2(1, 4)
  4. res3: Int = 5

5.4 柯里化函数(curried function)

柯里化函数把具有多个参数的函数转换成一条函数链, 每个节点上是单一参数

下面两个例子的函数定义是等价的:

def add(x: Int, y: Int) = x + y

def add(x: Int)(y: Int) = x + y //scala里柯里化的语法

  1. def curriedAdd(x: Int)(y: Int) = x + y
  2. curriedAdd(1)(2) //4
  3. val addOne = curriedAdd(1)_ // Int => Int
  4. addOne(2) //3

5.5 递归函数

递归函数是函数式编程中实现循环的一种技术

  1. def factorial(n: Int): Int = {
  2. if (n == 0) 1 else n * factorial(n-1)
  3. }

尾递归

  1. @annotation.tailrec
  2. def factorial(n: Int, m: Int): Int = {
  3. if (n == 0) m else factorial(n-1, n * m)
  4. }

@annotation.tailrec 告诉 scala使用尾递归, 这里内存中开辟一个栈用来存储m的值, 而不是n个栈来存储计算中间结果

5.6 例子

  1. def sum(f: Int => Int)(a: Int)(b: Int): Int = {
  2. @annotation.tailrec
  3. def loop(n: Int, acc: Int): Int = {
  4. if (n > b) acc
  5. else loop(n + 1, acc + f(n))
  6. }
  7. loop(a, 0)
  8. }
  9. sum(x => x)(1)(3) // 6
  10. sum(x => x * x)(1)(3) //14
  11. val s1 = sum(x => x * x)_ // 偏函数, _ 通配符用来匹配后面的参数
  12. s1(1)(3) //14

说明:

1.上面是个科里化函数, 有三个形式参数

  • 函数f, 函数类型 Int > Int
  • 形参a, 类型Int
  • 形参b, 类型Int

2.函数中定义了一个尾递归函数 loop, 实现相加

3.sum(x => x), 其中 x => x 是一个匿名函数

6. Scala 集合

scala.collection.immutable

6.1 List[T]

T 表示泛型


  1. // :: 连接操作符
  2. val a = List(1, 2, 3, 4)
  3. val b = 0 :: a
  4. //a: List[Int] = List(1, 2, 3, 4)
  5. //b: List[Int] = List(0, 1, 2, 3, 4)
  6. // Nil表示一个空列表
  7. // 先 z 连接 Nil, 然后 y 连接 z ...
  8. val c = "x" :: "y" :: "z" :: Nil
  9. //c: List[String] = List(x, y, z)
  10. // Any 类型
  11. val d = a ::: c
  12. //d: List[Any] = List(1, 2, 3, 4, x, y, z)
  13. // 返回List的第一个元素
  14. a.head
  15. c.head
  16. d.head
  17. //res0: Int = 1
  18. //res1: String = x
  19. //res2: Any = 1
  20. // 返回除了第一个元素之外元素组成的 List
  21. a.tail
  22. c.tail
  23. d.tail
  24. //res3: List[Int] = List(2, 3, 4)
  25. //res4: List[String] = List(y, z)
  26. //res5: List[Any] = List(2, 3, 4, x, y, z)
  27. a.isEmpty
  28. Nil.isEmpty
  29. //res6: Boolean = false
  30. //res7: Boolean = true
  31. def walkthru(l : List[Int]): String = {
  32. if (l.isEmpty) ""
  33. else l.head.toString + walkthru(l.tail)
  34. }
  35. walkthru(List(1, 3, 5, 7))
  36. //walkthru: walkthru[](val l: List[Int]) => String
  37. //res8: String = 1357

其他方法


  1. a.filter(x => x%2 == 1)
  2. //res9: List[Int] = List(1, 3)
  3. "hello life".toList
  4. //res10: List[Char] = List(h, e, l, l, o, , l, i, f, e)
  5. "hel 89 life".toList.filter(x => Character.isDigit(x))
  6. //res11: List[Char] = List(8, 9)
  7. "hel 89 life".toList.takeWhile(x=>x!='9')
  8. //res12: List[Char] = List(h, e, l, , 8)
  9. // _ 通配符
  10. c
  11. c.map(x => x.toUpperCase)
  12. c.map(_.toLowerCase)
  13. //res13: List[String] = List(x, y, z)
  14. //res14: List[String] = List(X, Y, Z)
  15. //res15: List[String] = List(x, y, z)
  16. a
  17. a.filter(_ % 2 == 1).map(_ + 10)
  18. //res16: List[Int] = List(1, 2, 3, 4)
  19. //res17: List[Int] = List(11, 13)
  20. val q = List(a, List(5, 6, 7))
  21. q.map(_.filter(_%2 == 0))
  22. q.flatMap(_.filter(_%2 == 0))
  23. //q: List[List[Int]] = List(List(1, 2, 3, 4), List(5, 6, 7))
  24. //res18: List[List[Int]] = List(List(2, 4), List(6))
  25. //res19: List[Int] = List(2, 4, 6)

6.2 归约操作

6.2.1 reduceleft

reduceLeft(op: (T,T) => T)

  1. a
  2. a.reduceLeft((x, y) => x+y)
  3. a.reduce(_ + _)
  4. // res20: List[Int] = List(1, 2, 3, 4)
  5. // res21: Int = 10
  6. // res22: Int = 10

6.2.2 foldLeft

foldLeft(z: U)(op: (U, T) => U)

a.foldLeft(1)(_ + _)

  1. a
  2. a.foldLeft(1)(_ + _)
  3. // res20: List[Int] = List(1, 2, 3, 4)
  4. // res23: Int = 11

7. Range & Stream & tuple & Map

7.1 Range & Stream

  1. 1 to 4
  2. (1 to 7 by 2).toList
  3. 1 until 6
  4. //res24: scala.collection.immutable.Range.Inclusive = Range 1 to 4
  5. // res25: List[Int] = List(1, 3, 5, 7)
  6. // res26: scala.collection.immutable.Range = Range 1 until 6
  7. // Stream 惰性求值
  8. 1 #:: 2 #:: 3 #:: Stream.empty
  9. //scala.collection.immutable.Stream[Int] = Stream(1, ?)
  10. val stream = (1 to 1000000).toStream
  11. //res28: scala.collection.immutable.Stream[Int] = Stream(1,?)
  12. stream.tail
  13. stream.head
  14. //res28: scala.collection.immutable.Stream[Int] = Stream(2, ?)
  15. //res29: Int = 1

7.2 tuple

  1. (1, 2)
  2. val tuple1 = (3, "hello", (1, "we"))
  3. tuple1._1
  4. tuple1._3._1
  5. // res30: (Int, Int) = (1,2)
  6. // tuple1: (Int, String, (Int, String)) = (3,hello,(1,we))
  7. // res31: Int = 3
  8. // res32: Int = 1
  9. def sumSq(in: List[Int]): (Int, Int, Int) = {
  10. in.foldLeft((0,0,0))((t,v) => (t._1 + 1, t._2 + v, t._3 + v*v))
  11. }
  12. a
  13. sumSq(a)
  14. //sumSq: sumSq[](val in: List[Int]) => (Int, Int, Int)
  15. // res33: List[Int] = List(1, 2, 3, 4)
  16. // res34: (Int, Int, Int) = (4,10,30)

7.3 Map(K, V)

  1. // 键的类型要一致, 值得类型可以不一致
  2. val map = Map(1 -> "david", 9 -> "ds")
  3. map(9)
  4. map.contains(1)
  5. map.contains(2)
  6. //scala.collection.immutable.Map[Int,String] = Map(1 -> david, 9 -> ds)
  7. // String = ds
  8. // Boolean = true
  9. // Boolean = false
  10. map.keys
  11. map.values
  12. // 下列操作map自身是不变的
  13. map + (8 -> 3)
  14. map
  15. map - 1
  16. map
  17. //scala.collection.immutable.Map[Int,Any] = Map(1 -> david, 9 -> ds, 8 -> 3)
  18. // Map(1 -> david, 9 -> ds)
  19. // scala.collection.immutable.Map[Int,String] = Map(9 -> ds)
  20. // scala.collection.immutable.Map[Int,String] = Map(1 -> david, 9 -> ds)
  21. // 添加多个元素, 如果添加的key已经存在, 则更新
  22. map ++ List(2 -> "Alice", 1-> "Hello")
  23. //Map(1 -> Hello, 9 -> ds, 2 -> Alice)
  24. map -- List(2, 1, 9)
  25. // Map()
  26. // 如果key不存在则忽略

7.4 快排

  1. def qSort(a: List[Int]): List[Int] = {
  2. if (a.length < 2) a
  3. else qSort(a.filter(a.head > _)) ++
  4. a.filter(a.head == _) ++
  5. qSort(a.filter(a.head < _))
  6. }
  7. qSort(List(1, 4, 2, 3, 9, 5))
  8. //res46: List[Int] = List(1, 2, 3, 4, 5, 9)







Scala 快速入门的更多相关文章

  1. Scala快速入门到精通 视频教程 百度云网盘下载地址

    Scala快速入门到精通  视频教程 百度云网盘下载地址 Scala快速入门到精通 下载地址链接:https://pan.baidu.com/s/1bqGIKyF 密码:ojwd

  2. scala快速入门之文档注释

    scala快速入门之文档注释 1.在项目栏的目录树中找到该源码,右击点击Show in Explorer, 即可找到该源码的本地路径,在路径中输入cmd 2.执行scaladoc -d  生成文档注释 ...

  3. Scala快速入门 - 基础语法篇

    本篇文章首发于头条号Scala快速入门 - 基础语法篇,欢迎关注我的头条号和微信公众号"大数据技术和人工智能"(微信搜索bigdata_ai_tech)获取更多干货,也欢迎关注我的 ...

  4. Scala快速入门(四)——继承、接口

    Scala快速入门(四)--继承.接口 一.继承 1.继承的概念:省略 2.模板: class Person(n:String,a:Int) { var name:String=n var age:I ...

  5. Spark(七) -- Scala快速入门

    Scala作为Spark的开发语言,想要成为Spark高手,精通Scala是必须要走的一条路 然后一门语言并不是你想精通就能够精通的,更何况是Scala这种面向对象又面向函数的编程语言,个人觉得其学习 ...

  6. Spark记录-scala快速入门

    1.hello world程序 object HelloWorld { def main(args: Array[String]) { println("Hello,World!" ...

  7. Scala快速入门-基础

    HelloWorld 从HelloWorld开始,使用scala IDE编辑器. 新建scala project 新建scala object 编写HelloWorld run as scala ap ...

  8. spark之scala快速入门

    scala和java都是在jvm之上的语言,相对来讲,scala热度比较低,其实并不是一个特别好的语言选择. 原因倒不是因为scala本身的缺点,而是使用人群不够多,论坛和社区不够活跃.这就跟社交软件 ...

  9. Scala快速入门-函数组合

    compose&andThen 两个函数组装为一个函数,compose和andThen相反 def f(test: String):String = { "f(" + te ...

随机推荐

  1. 【BZOJ2333】棘手的操作(左偏树,STL)

    [BZOJ2333]棘手的操作(左偏树,STL) 题面 BZOJ上看把... 题解 正如这题的题号 我只能\(2333\) 神TM棘手的题目... 前面的单点/联通块操作 很显然是一个左偏树+标记 ( ...

  2. ES2015 类中的静态方法

    在ES2015中,终于不用用函数原型来实现类系统,可以直接使用关键字class,下面是对class的静态属性的研究: 举例:一个Node类,每一个Node类之间都可以建立从属关系,每一个Node实例下 ...

  3. hive数据库的哪些函数操作是否走MR

    平时我们用的HIVE 我们都知道 select * from table_name 不走MR 直接走HTTP hive 0.10.0为了执行效率考虑,简单的查询,就是只是select,不带count, ...

  4. thoughtworks面试题分析与解答

    题目描述 A squad of robotic rovers are to be landed by NASA on a plateau on Mars. This plateau, which is ...

  5. iOS刚进入后台接受推送、打开推送调转到相应的界面

    刚进入后台的时候消息处理时候我用了本地推送!可以看我前边写的博客,怎么处理刚进入后台接收推送的案例,链接 /** 注释:打开推送的三种方式:-peter 1.apns的时候,结束进程退出后台:启动的时 ...

  6. Lastpass——密码管理工具

    Lastpass是一个优秀的在线密码管理器和页面过滤器,采用了强大的加密算法,自动登录/云同步/跨平台/支持多款浏览器. 我之前一直都在使用这个工具,不过都是在浏览器上以扩展的方式使用,在火狐浏览器上 ...

  7. 使用netty的第一个Hello World

    server端 package com.netty.test;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.Cha ...

  8. Git分支(3/5) -- 禁用 Fast Forward 合并

    添加一个分支, 并且换到该分支: git checkout -b add-text 然后我再index.html里面添加点文字, 并commit. 然后再修改README.md, 添加文字, comm ...

  9. 排序算法Java实现(希尔排序)

    算法描述:先将待排序序列的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,待整个待排序序列“基本有序”后,再对所有元素进行一次直接插入排序. packa ...

  10. poj-1031-fence(不是我写的,我只是想看着方便)

    题目大意: 有一个光源位于(0,0)处,一个多边形的围墙.围墙是“全黑”的,不透光也不反射光.距光源r处的光强度为I0=k/r,k为常数. 一块无穷窄高为h的墙上围墙受到的照度为dI=I0*|cosα ...