千家信息网

4、Scala函数式基础

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,一、内置控制结构1、if表达式val filenameNice = if (!args.isEmpty) args(0) else "default.txt"2、while循环不管是while还是do
千家信息网最后更新 2026年11月02日4、Scala函数式基础

一、内置控制结构

1、if表达式

val filenameNice = if (!args.isEmpty) args(0) else "default.txt"

2、while循环

不管是while还是do...while,我们都不能叫做表达式,而应该叫做循环,因为它们不会计算出一个新值。它们的值类型是Unit,在scala中Unit和()是相等的

def gcdLoop(x: Long, y: Long): Long = {

var a = x

var b = y

while (a != 0) {

val temp = a

a = b % a

b = temp

}

b

}


do...while...表达式


var line = ""

do {

line = scala.io.StdIn.readLine()

println("Read: " + line)

} while (line != "")


在scala中给var重新赋值,永远都是返回()(即Unit)

() != ""将永远返回true

var tempLine = ""

while ((tempLine = scala.io.StdIn.readLine()) != "") // This doesn't work!

println("Read: " + tempLine)


因为while循环不计算出值,所以while的代码不那么的函数式,一般都会含有var变量,

scala选择保留while是因为有些场景使用while的代码的可读性还是很强的

采用递归来消除掉var

def gcd(x: Long, y: Long): Long =

if (y == 0) x else gcd(y, x % y)

3、for表达式

用for表达式迭代一个任意集合

val filesHere = (new java.io.File(".")).listFiles

for (file <- filesHere)

println(file)

for表达式中的过滤

for (

file <- filesHere

if file.isFile

if file.getName.endsWith(".scala")

) println(file)


嵌套迭代(nested iteration)

def grep(pattern: String) =

for (

file <- filesHere

if file.getName.endsWith(".scala");

line <- fileLines(file)

if line.trim.matches(pattern)

) println(file + ": " + line.trim)

可以在迭代的过程中,绑定中间值到一个变量

上面的()可以换成{},这样每一个语句后面的分号就可以省略

def grepBindValue(pattern: String) =

for {

file <- filesHere

if file.getName.endsWith(".scala")

line <- fileLines(file)

trimmed = line.trim

if trimmed.matches(pattern)

} println(file + ": " + trimmed)

for ... yield ... 可以生成一个新的集合

//返回的是Array,是因为filesHere的类型是Array

def scalaFiles: Array[File] =

for {

file <- filesHere

if file.getName.endsWith(".scala")

} yield file


val forLineLengths: List[Int] =

for {

file <- filesHere.toList

if file.getName.endsWith(".scala")

line <- fileLines(file)

trimmed = line.trim

if trimmed.matches(".*object.*")

} yield trimmed.length


4、异常处理

scala中抛异常使用throw关键字,异常的捕获用catch关键字。捕获到异常后,可以计算并返回一个值

val n = 5

val half: Int =

if (n % 2 == 0)

n / 2

else

throw new RuntimeException("n must be even")

println(half)


try {

//val f = new FileReader("input.txt") //这个会抛FileNotFoundException

// Use and close file

throw new IOException("test")

} catch {

case e @(_: FileNotFoundException | _: IOException) => {

// Handle missing file

println("All Exception = " + e.getMessage)

}

case ex: Exception => {

// Handle other I/O error

println("IOException = " + ex.getMessage)

}

}


val file = new FileReader("input.txt")

try {

// Use the file

} finally {

file.close() // Be sure to close the file

}

5、break和continue

非得使用break的话,我们可以使用scala.util.control中的break

import scala.util.control.Breaks._

import java.io._

val in = new BufferedReader(new InputStreamReader(System.in))

breakable {

while (true) {

println("? ")

if (in.readLine() == "") break

}

}

二、函数

1、本地函数。定义在函数内部的函数为本地函数,智能被此函数内部调用。

def processFile(filename: String, width: Int) = {

//本地函数

def processLine(line: String) = {

if (line.length > width)


println(filename + ": " + line.trim)

}


val source = Source.fromFile(filename)

for (line <- source.getLines())

processLine(line)

}

2、first class function 函数可以作为函数的参数进行传递

3、函数的参数

不定长参数

def echo(args: String*) =

for (arg <- args) println(arg)


使用参数名字来给参数设置值

def speed(distance: Float, time: Float): Float =

distance / time

speed(distance = 100, time = 10)


默认参数值

def printTime(out: java.io.PrintStream = Console.out) =

out.println("time = " + System.currentTimeMillis())

printTime()

printTime(Console.err)

4、函数闭包

函数捕获一个自由变量而变成一个闭包。 每次调用函数的时候都产生一个新的闭包。

var more = 1

val addMore = (x: Int) => x + more //函数捕获一个自由变量而变成一个闭包

addMore(10)


当自由变量的值改变的时候,闭包对自由变量的改变也是可以捕获的到

more = 9999

addMore(10)


val someNumbers = List(-11, -10, -5, 0, 5, 10)

var sum = 0

someNumbers.foreach(sum += _)

println(sum)

5、尾递归

什么是尾递归呢?如果调用自身方法的动作是函数体的最后一个动作的话,那么这个递归就是一个尾递归

递归:更函数式、简洁以及没有var,但是函数的调用可能会消耗点时间。while循环是命令式编程,可能会更高效的,因为没有方法的调用。但是如果是尾递归的话,编译器是会优化的,其效率和while循环是一样的

可以使用注解tailrec来标志是否为尾递归

@tailrec

def boom(x: Int): Int =

if (x == 0) throw new Exception("boom!")

else boom(x - 1)


尾递归的限制,以下递归,不会进行尾递归优化,因为jvm的指令集使得尾递归的优化受限

递归调用的函数不是函数体所在的函数

def isEven(x: Int): Boolean =

if (x == 0) true else isOdd(x - 1)

def isOdd(x: Int): Boolean =

if (x == 0) false else isEven(x - 1)


三、高阶函数及函数柯里化

高阶函数(high-order functions)就是用函数作为参数的函数。高阶函数可以减少冗余代码,高阶函数可以使得客户端代码简洁。

def filesEnding(query: String) =

for (file <- filesHere; if file.getName.endsWith(query))

yield file


def filesContaining(query: String) =

for (file <- filesHere; if file.getName.contains(query))

yield file


改造后:

private def filesMatching(matcher: String => Boolean) =

for (file <- filesHere; if matcher(file.getName))

yield file


柯里化

//柯里化函数(curring function)

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

curriedSum(1)(2)

//说明柯里化的过程

def first(x: Int) = (y: Int) => x + y

val second = first(1)

second(2)


示例:自定义循环控制语句

var i = 10

while (i == 0) {

i -= 1

println(i)

}


until(i == 0) {

i -= 1

println(i)

}


def until(condition: => Boolean)(block: => Unit) {

if (!condition) {

block

until(condition)(block)

}

}


by name by value

by name 执行的时候才执行,by value调用就执行

//by-name parameter

def byNameAssert(predicate: => Boolean) =

if (assertionsEnabled && !predicate)

throw new AssertionError


byNameAssert(5 > 3)


//by-value parameter

def boolAssert(predicate: Boolean) =

if (assertionsEnabled && !predicate)

throw new AssertionError

boolAssert(5 > 3)


函数 递归 参数 变量 表达式 循环 闭包 自由 代码 高阶 柯里 时候 迭代 简洁 关键 关键字 动作 就是 方法 类型 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网和科技创新 互联网科技排名 苏州互联网科技贷款公司 互联网科技公司做什么 广州慧亚互联网科技怎么样 互联网科技热点资讯 欧洲十大科技互联网公司 广州恒生互联网科技有限 互联网科技有哪些公司 崇明区互联网教育科技诚信经营 移动互联网年度科技创新 互联网科技扶贫时间 佛山市拉法互联网科技有限公司 江苏互联网智能科技软件 全球科技与互联网公司市值变化 国产互联网科技公司 互联网公司属于科技吗 互联网金融运营模式中的金融科技 恒生科技指数 中概互联网 杭州科技互联网公司有哪些 紫鲸互联网科技 互联网金融科技平台 上海电发互联网科技有限公司 互联网教育科技公司vipkid 剑昆互联网络科技有限公司临桂 互联网科技革命什么开始 长沙茂晟互联网科技有限公司 江苏互联网科技小贷 互联网科技企业商标注意事项 科技互联网经济论坛
0