Scala程序设计—基础篇

Scala程序设计—基础篇

地址:Scala程序设计—基础篇

1章 函数式编程思想

本章讲述了函数式编程的概念、术语

1-1 课程介绍

Scala特性:

Scalable编程语言

纯正的面向对象语言

函数式语言

无缝的Java互操作

Scala特性

1-2 scala函数式编程思想

什么是函数式编程?

在计算机科学领域,函数式编程是一种编程范式,它是一种构建计算机程序结构的方法和风格,它把程序当做数学函数的求值过程并且避免了改变状态和可变的数据。

函数式编程的重要概念

纯函数:不具有副作用,即不改变函数作用域之外变量的值。

副作用:是状态的变化(mutation) 例子:修改全局变量、抛出异常、IO读写、t调用有副作用的函数

引用透明(Referential Transparency)

对于相同的输入,总是得到相同的输出

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

不变性(Immutability)为了获得引用透明性,任何值都不能变化

函数是一等公民(First-class Function)

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

高阶函数(Higher order Function)

闭包(Closure)

表达式求值策略:严格求值 和 非严格求值

Call By Value vs Call By Name

惰性求值(Lazy Evaluation)

递归函数(Recursive Function)

递归实现循环

尾递归(Tail Recursion)

函数式编程的关键词

函数式编程的关键词

函数值编程的优点:

生产效率高、同样功能的程序,Lisp代码的长度可能是C代码的1/7~~~1/10

易于推理(Reasoning)

并行编程,多核计算、云计算

http://www.slideshare.net/Ordersky/oscon-keynote-working-hard-to-keep-it-simple

2章 Scala开发环境

本章介绍了Scala的开发环境-REPL和IDE

2-1 scala环境搭建

安装Jdk:

下载安装Scala:https://www.scala-lang.org/download/

下载安装SBT(Simple Build Tool ):https://www.scala-sbt.org/download.html?_ga=2.212214996.1146994929.1526990837-1074418497.1526990748

SBT是SCALA 平台上标准的项目构建工具,当然你要用它来构建其他语言的项目也是可以的。SBT 没有Maven那么多概念和条条框框,但又比IVY要更加灵活,可以认为是一个精简版的Maven吧。

REPL:Read Evaluate Print Loop 交互式程序运行环境,非常轻量级,用于做实验的 (可以理解为shell交互环境)

启动REPL:

1 sbt console

2 scala

3章 Scala的语言基础

本章讲解了Scala的变量和表达式

3-1 scala基础语法之变量

val 常量 var 变量 lazy val 惰性求值常量:该变量可能不会被用到 ,只有当第一次使用时 使用 lazy val

三种变量修饰符

3-2 Scala数据类型

Scala类型体系:

根类:Any

子类:

AnyVal:值类型

AnyRef:引用类型的父类

Scala类型体系

和java一样,低精度可以向高精度自动转化,高精度不可以想低精度转换

函数返回nothing表明程序异常,

String

String

3-3 Scala函数与代码块

代码块

代码块

函数:

函数
def hello(name: String): String = {
  s"Hello,${name}"
}
hello("boy")

def hello2(name:String)={
  s"Hello,${name}"
}
hello2("123")

def add(x:Int,y:Int) ={x+y
}
def add2(x:Int,y:Int) =x+y
add(1,7)

3-4 Scala基础 if与for

if是表达式,不是语句

if是表达式

for comprehension 循环

for循环
val list = List("alice", "bob", "cathy");

for (
  s <- list //generator
) println(s)


for (
  s <- list
  if (s.length > 3) //filter
) println(s)

val result_for = for {
  s <- list
  s1 = s.toUpperCase() //variable binding
  if(s1 != "")
} yield(s1)  //generate new collection

3-5 Scala基础 try与match表达式

try表达式

try表达式

_:通配符

val result_try = try {
  Integer.parseInt("boy")
} catch {
  case _ => 0
} finally {
  println("always be printed")
}

输出:
always be printed
result_try: Int = 0

match表达式

match表达式
val code = 5
val result_match = code match {
  case 1 => "one"
  case 2 => "two"
  case _ => "others"
}

输出:
code: Int = 5
result_match: String = others

4章 求值策略

4-1 求值策略

本章讲解了Call By Value和Call By Name的区别

求值策略(Evaluation Strategy)有两种:

Call By Value - 对函数实参求值,且仅求值一次

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

Scala通常使用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
image.png
def bar(x: Int, y: => Int): Int = 1

def loop(): Int = loop

bar(1, loop)     //输出:res2: Int = 1

bar(loop, 1)     //死循环

5章 高阶函数

本章讲解了Scala高阶函数的概念和语法

5-1 Scala 函数与匿名函数

函数是一等公民

函数是一等公民

函数类型

在Scala语言中,函数类型的格式为A => B,表示一个接受类型A的参数,并返回类型B的函数

例子:Int => String 是把整型映射为字符串的函数类型

高阶函数

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

//函数operate,f是一个函数,接受两个int的参数并且返回一个int的值,在函数operate体内调用f函数  
def operate(f: (Int, Int) => Int) ={
    f(4,4)
}
//返回值是一个函数
def greeting() = (name: String) => {"hello" + " " + name}

匿名函数

匿名函数(Anonymous Function),就是函数常量,也称为函数文字量(Function Literal)

在Scala里,匿名函数的定义格式为: (形参列表) => {函数体}

匿名函数的例子:

例子1: (x: Int) => x*x
例子2: (x: Int,y: Int) => x+y
例子3:
var add = (x: Int, y: Int) => x + y //add是一个具有函数类型的变量
add(1, 2) //返回值:Int=3

def greeting() = (name: String) => {
  s"Hello $name"
}
greeting()("World")

def greeting(age: Int) = (name: String) => {
  s"Hello $name,your age is $age"
}
greeting(23)("Flygar")

5-2 Scala 柯里化

柯里化函数(Curried Function)把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。

例子:

以下两个add函数定义是等价的

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

柯里化的例子

def curriedAdd(a: Int)(b: Int) = a + b
curriedAdd(2)(2)  //4

val addOne = curriedAdd(1)_  //Int => Int  下换线匹配的是b
addOne(2)    //3

5-3 Scala 递归与尾递归

递归函数(Recursive Function)在函数式编程中是实现循环的一种技术。

例子:计算你n!

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

为了防止递归时栈溢出,进行优化使用尾递归函数

尾递归函数

尾递归函数(Tail Recursive Function)中所有递归形式的调用都出现在函数的末尾。

当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的

尾递归的例子

//5!
@annotation.tailrec
def factorial(n: Int, m: Int): Int = 
    if(n <= 0) m
    else factorial(n-1, m*n)
factorial(5,1)

5-4 例子

综合性例子:求\sum_{i=a}^b f(x)

求$\sum_{i=a}^b$ f(x)
//三个参数:f a b
def sum(f: Int => Int)(a: Int)(b: Int): Int = {
  //a到b的循环,对f(x)求解,然后累加f(x)
  @annotation.tailrec
  def loop(n: Int, acc: Int): Int = {
    if (n > b) {
      println(s"n=${n}, acc=${acc}")
      acc
    } else {
      println(s"n=${n}, acc=${acc}")
      loop(n + 1, acc + f(n))
    }
  }

  loop(a, 0)
}

sum(x => x)(1)(5)

sum(x => x * x)(1)(5)

sum(x => x * x * x)(1)(5)

val sumSquare = sum(x => x * x)_
sumSquare(1)(5)

6章 Scala Immutable Collection

本章讲解了Scala Immutable Collection的List、Range、Stream和Map

6-1 Scala Collections-list基本使用

scala.collection.immutable

scala.collection.immutable

List[T]

scala> val a = List(1,2,3,4)
a: List[Int] = List(1, 2, 3, 4)

//::  连接操作符 左边是成员 右边是list
scala> val b =0 :: a
b: List[Int] = List(0, 1, 2, 3, 4)

scala> val c = "x" :: "y" :: "z" :: Nil
c: List[String] = List(x, y, z)

scala> "z" :: Nil
res0: List[String] = List(z)

scala> "y" :: res0
res1: List[String] = List(y, z)

scala> "x" :: res1
res2: List[String] = List(x, y, z)

scala> val d = a ::: c
d: List[Any] = List(1, 2, 3, 4, x, y, z)

//a.head返回list第一个元素 a.tail返回除了第一个元素外的其他元素(尾列表) a.isEmpty判断是否为空

6-2 Scala list高级使用

a.filter过滤函数

//a.filter过滤函数
scala> val a = List(1,2,3,4)
scala> a.filter(x => x%2 ==1 )
res10: List[Int] = List(1, 3)

"".toList.filter

scala>  "99 Red Balloons".toList.filter(x => Character.isDigit(x))
res11: List[Char] = List(9, 9)

"".toList.takeWhile

scala> "99 Red Ballons".toList.takeWhile(x => x != 'B')
res12: List[Char] = List(9, 9,  , R, e, d,  )

6-3 Scala list-map

map映射:用来将一个列表中的每个元素进行映射的函数

//转乱成大写
scala> c.map(x => x.toUpperCase)
res13: List[String] = List(X, Y, Z)

//通配符
scala> c.map(_.toUpperCase)
res14: List[String] = List(X, Y, Z)

//通配符
scala> c.map(_.toUpperCase)
res17: List[String] = List(X, Y, Z)

//通配符
scala> a.filter(_%2 == 1)
res18: List[Int] = List(1, 3)

//通配符过滤后每个元素加10
scala> a.filter(_%2 == 1).map(_ + 10)
res19: List[Int] = List(11, 13)

//取q中的偶数
scala> val q = List(a, List(4,5,6))
q: List[List[Int]] = List(List(1, 2, 3, 4), List(4, 5, 6))

scala> q.map(x => x.filter( _%2 == 0))
res20: List[List[Int]] = List(List(2, 4), List(4, 6))

scala>  q.map(_.filter(_%2 == 0))
res21: List[List[Int]] = List(List(2, 4), List(4, 6))

//flatMap
scala>  q.flatMap(_.filter(_%2 == 0))
res23: List[Int] = List(2, 4, 4, 6)

6-4 Scala reduceLeft与flodLeft

reduceLeft 规约操作

reduceLeft 规约操作
scala> a
res25: List[Int] = List(1, 2, 3, 4)

scala> a.reduceLeft((x, y) => x+y)
res26: Int = 10

scala> a.reduce( _ + _)
res27: Int = 10

foldLeft规约操作

foldLeft规约操作
scala> a.foldLeft(0)( _+_ )
res28: Int = 10

scala> a.foldLeft(1)( _*_ )
res29: Int = 24

6-5 Scala Rang与Stream

Rang

//to是闭区间 until是开区间
scala> 1 to 10
res34: scala.collection.immutable.Range.Inclusive = Range 1 to 10

scala> 1 to 10 by 2
res35: scala.collection.immutable.Range = inexact Range 1 to 10 by 2

scala> (1 to 10).toList
res36: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> 1 until 10
res37: scala.collection.immutable.Range = Range 1 until 10

scala> (1 until 10).toList
res38: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

Stream

惰性求值列表,只求第一个值

scala> 1 #:: 2 #:: 3 #:: Stream.empty
res39: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> val stream = (1 to 1000000).toStream
stream: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> stream.head
res40: Int = 1

scala> stream.tail
res41: scala.collection.immutable.Stream[Int] = Stream(2, ?)

6-6 Scala tuple与map

tuple:元组,类似于数据库中的记录

//如果有两个值则称为对pair
scala> (1,2)
res44: (Int, Int) = (1,2)
//简写
scala> 1 -> 2
res45: (Int, Int) = (1,2)
//类似于数据库中的记录
scala> (1, "Alice", "Math", 95.5)
res46: (Int, String, String, Double) = (1,Alice,Math,95.5)

scala> val t = (1, "Alice", "Math", 95.5)
t: (Int, String, String, Double) = (1,Alice,Math,95.5)
//取值
scala> t._1
res47: Int = 1

scala> t._2
res48: String = Alice

scala> t._3
res49: String = Math

scala> t._4
res50: Double = 95.5

//求list的长度,元素之和,元素平方之和
scala> a
res52: List[Int] = List(1, 2, 3, 4)
//输入list  输出:tuple(Int,Int,Int)  foldLeft规约操作,t是元组(0,0,0,0),list中的每个值作为输出参数v 然后返回一个tuple 
scala> 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))
sumSq: (in: List[Int])(Int, Int, Int)

scala> sumSq(a)
res51: (Int, Int, Int) = (4,10,30)

Map[K,V]

//新建
scala> val p = Map(1 -> "David", 9 -> "Elwood")
p: scala.collection.immutable.Map[Int,String] = Map(1 -> David, 9 -> Elwood)
//取值
scala> p(1)
res55: String = David

scala> p(9)
res56: String = Elwood

scala> p.contains(1)
res57: Boolean = true

scala> p.contains(2)
res58: Boolean = false
//取key
scala> p.keys
res59: Iterable[Int] = Set(1, 9)
//取values
scala> p.values
res60: Iterable[String] = MapLike.DefaultValuesIterable(David, Elwood)
//添加键值对
scala> p + (8 -> "Archer")
res61: scala.collection.immutable.Map[Int,String] = Map(1 -> David, 9 -> Elwood, 8 -> Archer)
//删除键值对
scala> p - 1
res62: scala.collection.immutable.Map[Int,String] = Map(9 -> Elwood)
//添加多个值到map
scala> p ++ List(2 -> "Alice", 5 -> "Bob")
res69: scala.collection.immutable.Map[Int,String] = Map(1 -> David, 9 -> Elwood, 2 -> Alice, 5 -> Bob)
//删除多个值
scala> p -- List(1,9,2)
res70: scala.collection.immutable.Map[Int,String] = Map()
//同时操作
scala> p ++ List(2 -> "Alice", 5 -> "Bob") -- List(1,9,2)
res72: scala.collection.immutable.Map[Int,String] = Map(5 -> Bob)

6-7 Scala 快速排序案例

Scala 快速排序案例

启动:paste大规模编辑模式

scala> :paste
// Entering paste mode (ctrl-D to finish)

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))

// Exiting paste mode, now interpreting.

qSort: (a: List[Int])List[Int]

scala> qSort(List(3,1,2))
res73: List[Int] = List(1, 2, 3)

scala> qSort(List(9,5,6,3,5,7,8,23))
res74: List[Int] = List(3, 5, 5, 6, 7, 8, 9, 23)

Boy-20180528

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343