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

scala之父 Martin Odersky

1. 函数式编程

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

1.1 函数式编程的重要概念

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

1.副作用

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

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

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

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

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

2.引用透明性

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

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

var x = new StringBuild("Hello")
var y = x.append("world")
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

例子

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

5. Scala函数

scala中函数是第一等公民:

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

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

5.1 函数类型

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

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

5.2 高阶函数

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

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

5.3 匿名函数

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

scala中匿名函数的格式为:

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

scala> (x: Int, y: Int) => x+y
res2: (Int, Int) => Int = $$Lambda$1209/886693791@35c8be21 scala> res2(1, 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里柯里化的语法

def curriedAdd(x: Int)(y: Int) = x + y

curriedAdd(1)(2)    //4

val addOne = curriedAdd(1)_     // Int => Int
addOne(2) //3

5.5 递归函数

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

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

尾递归

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

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

5.6 例子

def sum(f: Int => Int)(a: Int)(b: Int): Int = {
@annotation.tailrec
def loop(n: Int, acc: Int): Int = {
if (n > b) acc
else loop(n + 1, acc + f(n))
}
loop(a, 0)
} sum(x => x)(1)(3) // 6 sum(x => x * x)(1)(3) //14 val s1 = sum(x => x * x)_ // 偏函数, _ 通配符用来匹配后面的参数
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 表示泛型


// :: 连接操作符
val a = List(1, 2, 3, 4)
val b = 0 :: a
//a: List[Int] = List(1, 2, 3, 4)
//b: List[Int] = List(0, 1, 2, 3, 4) // Nil表示一个空列表
// 先 z 连接 Nil, 然后 y 连接 z ...
val c = "x" :: "y" :: "z" :: Nil
//c: List[String] = List(x, y, z) // Any 类型
val d = a ::: c
//d: List[Any] = List(1, 2, 3, 4, x, y, z) // 返回List的第一个元素
a.head
c.head
d.head
//res0: Int = 1
//res1: String = x
//res2: Any = 1 // 返回除了第一个元素之外元素组成的 List
a.tail
c.tail
d.tail //res3: List[Int] = List(2, 3, 4)
//res4: List[String] = List(y, z)
//res5: List[Any] = List(2, 3, 4, x, y, z) a.isEmpty
Nil.isEmpty
//res6: Boolean = false
//res7: Boolean = true def walkthru(l : List[Int]): String = {
if (l.isEmpty) ""
else l.head.toString + walkthru(l.tail)
} walkthru(List(1, 3, 5, 7)) //walkthru: walkthru[](val l: List[Int]) => String
//res8: String = 1357

其他方法


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

6.2 归约操作

6.2.1 reduceleft

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

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

6.2.2 foldLeft

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

a.foldLeft(1)(_ + _)

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

7. Range & Stream & tuple & Map

7.1 Range & Stream

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

7.2 tuple

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

7.3 Map(K, V)

// 键的类型要一致, 值得类型可以不一致
val map = Map(1 -> "david", 9 -> "ds")
map(9)
map.contains(1)
map.contains(2)
//scala.collection.immutable.Map[Int,String] = Map(1 -> david, 9 -> ds)
// String = ds
// Boolean = true
// Boolean = false map.keys
map.values // 下列操作map自身是不变的
map + (8 -> 3)
map
map - 1
map //scala.collection.immutable.Map[Int,Any] = Map(1 -> david, 9 -> ds, 8 -> 3)
// Map(1 -> david, 9 -> ds)
// scala.collection.immutable.Map[Int,String] = Map(9 -> ds)
// scala.collection.immutable.Map[Int,String] = Map(1 -> david, 9 -> ds) // 添加多个元素, 如果添加的key已经存在, 则更新
map ++ List(2 -> "Alice", 1-> "Hello")
//Map(1 -> Hello, 9 -> ds, 2 -> Alice) map -- List(2, 1, 9)
// Map()
// 如果key不存在则忽略

7.4 快排

def qSort(a: List[Int]): List[Int] = {
if (a.length < 2) a
else qSort(a.filter(a.head > _)) ++
a.filter(a.head == _) ++
qSort(a.filter(a.head < _))
} qSort(List(1, 4, 2, 3, 9, 5))
//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. POJ1741

    树分治,每次把每个点的deep取出,排序...尺取法... # include <stdio.h> # include <stdlib.h> # include <ios ...

  2. Spring MVC执行流程

    SpringMVC是隶属于Spring Web中的一部分, 属于表现层的框架. 其使用了MVC架构模式的思想, 将Web层进行职责解耦, 使用请求-响应模型简化Web开发 SpringMVC通过中央调 ...

  3. ubuntu中eclipse 不支持gbk编码问题解决办法

    今天在ubuntu 下, 把Windows下工程导入Linux下Eclipse中,由于工程代码,是GBK编码,而Ubuntu默认不支持GBK编码,所以,要让Ubuntu支持GBK. 方法如下: 1.修 ...

  4. jni 类初始化失败(nested exception is java.lang.NoClassDefFoundError)

    nested exception is java.lang.NoClassDefFoundError: Could not initialize class com.netease.facedetec ...

  5. SSM 使用 mybatis 分页插件 pagehepler 实现分页

    使用分页插件的原因,简化了sql代码的写法,实现较好的物理分页,比写一段完整的分页sql代码,也能减少了误差性. Mybatis分页插件 demo 项目地址:https://gitee.com/fre ...

  6. PHP的日志记录-错误与异常记录

    PHP的日志记录-错误与异常记录 提到 Nginx + PHP 服务的错误日志,我们通常能想到的有 Nginx 的 access 日志.error 日志以及 PHP 的 error 日志.虽然看起来是 ...

  7. 教你如何前后端完全分离(非api、ajax)

    我的前后分离,不是api,不是ajax,我这里只讨论html与后端结合 前话 曾经风靡一时的dedecms相信做网站的十有八.九都知道,还有那么一些不是技术出生的人,通过看一下文档,也能访问出网站出来 ...

  8. ASP.NET MVC编程——视图

    1Razon语法 使用@符号后接C#或VB.NET语句的方式. 基本规则 1)变量 @后直接变量即可 2)代码块 为使用表达式或多行代码,@后跟大括号将多行代码包括在大括号中 3)"+&qu ...

  9. 笔记:Spring Cloud Eureka 服务治理

    Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件的一部分,基于 Netflix Eureka 做了二次封装,主要负责完成微服务架构中的服务治理功能,服务 ...

  10. flex布局之兼容

    Android 2.3 开始就支持旧版本 display:-webkit-box; 4.4 开始支持标准版本 display: flex; IOS  6.1 开始支持旧版本 display:-webk ...