Scala - 快速学习08 - 函数式编程:高阶函数
函数式编程的崛起
函数是第一等公民
- 可以作为实参传递给另外一个函数
- 可以作为返回值
- 可以赋值给变量
- 可以存储在数据结构里
def greeting() = (name: String) => { s"Hello" + " " + name }//> greeting: ()String => Stringgreeting()("World") //> res0: String = Hello Worlddef greeting2(age: Int) = (name: String) => { s"Hello $name, your age is $age" }//> greeting2: (age: Int)String => Stringgreeting2(29)("Anliven") //> res2: String = Hello Anliven, your age is 29
函数类型和值
- Scala语法要求函数的“值”采用“=>”而不是“=”。
- 在Scala中,函数类型的格式为 A => B,表示一个接受类型A的参数,并返回类型B的函数。
def test(x: Int): Int = { x + 1 } //> test: (x: Int)Intdef test1(x: Int) = x + 1 //> test1: (x: Int)Intval test2: Int => Int = { (x: Int) => x + 1 } //> test2 : Int => Int = testrepl$$$Lambda$8/290658609@c818063val test3 = { (x: Int) => x + 1 } //> test3 : Int => Int = testrepl$$$Lambda$9/1057941451@75bd9247def test5(x: Int, y: Int) = x + y //> test5: (x: Int, y: Int)Intvar test6 = (x: Int, y: Int) => x + y //> test6 : (Int, Int) => Int = testrepl$$$Lambda$10/1513712028@3cb5cdbatest6(2, 6)
匿名函数
val myNum: Int => Int = (x: Int) => { x * 2 } //> myNum : Int => Int = testrepl$$$Lambda$3/2093176254@799f7e29val myNum2 = (x: Int) => x * 2 //> myNum2 : Int => Int = testrepl$$$Lambda$9/804581391@c818063val myNum3: Int => Int = (x) => x * 2 //> myNum3 : Int => Int = testrepl$$$Lambda$10/1057941451@75bd9247myNum(3) //> res0: Int = 6myNum2(3) //> res1: Int = 6myNum3(3) //> res2: Int = 6def test1(x: Int): Int = { x * x } //> test1: (x: Int)Intdef test2(x: Int) = x * x //> test2: (x: Int)Int(x: Int) => x * x //> res0: Int => Int = testrepl$$$Lambda$8/431687835@5ba23b66val test3 = (x: Int) => x * x //> test3 : Int => Int = testrepl$$$Lambda$9/804581391@c818063val test4: Int => Int = (x) => x * x //> test4 : Int => Int = testrepl$$$Lambda$10/1057941451@75bd9247test1(3) //> res1: Int = 9test2(3) //> res2: Int = 9test3(3) //> res3: Int = 9test4(3) //> res4: Int = 9
- 第1行:把匿名函数"(x: Int) => { x * 2 }"定义为一个值,赋值给myNum变量
- 第2行:省略myNum2的类型声明“Int=>Int”,省略匿名函数的表达式花括号
- 第3行:省略x的类型声明,省略匿名函数的表达式花括号
def test1(x: Int, y: Int): Int = { x + y } //> test1: (x: Int, y: Int)Intdef test2(x: Int, y: Int) = x + y //> test2: (x: Int, y: Int)Int(x: Int, y: Int) => x + y //> res0: (Int, Int) => Int = testrepl$$$Lambda$8/290658609@c818063var test3 = (x: Int, y: Int) => x + y //> test3 : (Int, Int) => Int = testrepl$$$Lambda$9/1057941451@75bd9247var test4: (Int, Int) => Int = (x, y) => { x + y }//> test4 : (Int, Int) => Int = testrepl$$$Lambda$10/2101440631@7dc36524test1(2, 6) //> res1: Int = 8test2(2, 6) //> res2: Int = 8test3(2, 6) //> res3: Int = 8test4(2, 6) //> res4: Int = 8
闭包
- 如果引用的变量是自由变量,没有绑定具体的值,那么此时这个函数是“开放的”。
- 如果引用的自由变量被绑定具体的值后,不再是“自由变量”,从而构成一个封闭的函数,那么此时这个函数“被关闭”了。
var more = 1 //> more : Int = 1val addMore = (x: Int) => x + more //> addMore : Int => Int = testrepl$$$Lambda$9/240650537@1cd072a9addMore(10) //> res0: Int = 11more = 9addMore(10) //> res1: Int = 19
def plusStep(step: Int) = (num: Int) => num + step//> plusStep: (step: Int)Int => Intval myFunc = plusStep(3) //> myFunc : Int => Int = testrepl$$$Lambda$8/209813603@2f7c7260println(myFunc(10)) //> 13
高阶函数
def f(x: Int, y: Int) = x + y //> f: (x: Int, y: Int)Intdef operate(f: (Int, Int) => Int) = { f(4, 4) } //> operate: (f: (Int, Int) => Int)Intoperate(f)
//给定两个数区间中的所有整数求和def sumInts(a: Int, b: Int): Int = {if (a > b) 0 else a + sumInts(a + 1, b)} //> sumInts: (a: Int, b: Int)IntsumInts(1, 5) //> res0: Int = 15//定义了一个新的函数sum,以函数f为参数def sum(f: Int => Int, a: Int, b: Int): Int = {if (a > b) 0 else f(a) + sum(f, a + 1, b)} //> sum: (f: Int => Int, a: Int, b: Int)Int//定义了一个新的函数self,该函数的输入是一个整数x,然后直接输出x自身def self(x: Int): Int = x //> self: (x: Int)Int//重新定义sumInts函数def sumInts2(a: Int, b: Int): Int = sum(self, a, b)//> sumInts2: (a: Int, b: Int)IntsumInts2(1, 5) //> res1: Int = 15
def sum(f: Int => Int, a: Int, b: Int): Int = {if (a > b) 0 else f(a) + sum(f, a + 1, b)} //> sum: (f: Int => Int, a: Int, b: Int)Intdef self(x: Int): Int = x //> self: (x: Int)Intdef square(x: Int): Int = x * x //> square: (x: Int)Intdef powerOfTwo(x: Int): Int = if (x == 0) 1 else 2 * powerOfTwo(x - 1)//> powerOfTwo: (x: Int)Intdef sumInts(a: Int, b: Int): Int = sum(self, a, b)//> sumInts: (a: Int, b: Int)Intdef sumSquared(a: Int, b: Int): Int = sum(square, a, b)//> sumSquared: (a: Int, b: Int)Intdef sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b)//> sumPowersOfTwo: (a: Int, b: Int)Intprintln(sumInts(1, 5)) //> 15println(sumSquared(1, 5)) //> 55println(sumPowersOfTwo(1, 5)) //> 62
- sumInts函数:求连续整数的和
- sumSquared函数:求连续整数的平方和
- sumPowersOfTwo函数:求连续整数的关于2的幂次和
占位符语法
println("Testing, Scala!") //> Testing, Scala!val numList = List(-3, -5, 1, 6, 9) //> numList : List[Int] = List(-3, -5, 1, 6, 9)numList.filter(x => x > 0) //> res0: List[Int] = List(1, 6, 9)numList.filter(_ > 0) //> res1: List[Int] = List(1, 6, 9)
柯里化
def add(x: Int, y: Int) = x + y //> add: (x: Int, y: Int)Intadd(1, 2) //> res0: Int = 3def addCurried(x: Int)(y: Int) = x + y //> addCurried: (x: Int)(y: Int)IntaddCurried(1)(2) //> res1: Int = 3val addOne = addCurried(1)_ //> addOne : Int => Int = TestScala$$$Lambda$8/6738746@7cf10a6faddOne(2) //> res2: Int = 3
递归
def factorial(n: Int): Int =if (n <= 0) 1else n * factorial(n - 1) //> factorial: (n: Int)Intfactorial(5) //> res0: Int = 120
尾递归
package testscalaobject TestScala {def main(args: Array[String]) {println("Testing, Scala!")val res = factorial2(5, 1)println(res)}@annotation.tailrecdef factorial2(n: Int, m: Int): Int =if (n <= 0) melse factorial2(n - 1, m * n)}
示例:求整数a到b的相加之和
def sum(f: Int => Int)(a: Int)(b: Int): Int = {@annotation.tailrecdef 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: (f: Int => Int)(a: Int)(b: Int)Intsum(x => x)(1)(5) //> n=1,acc=0//| n=2,acc=1//| n=3,acc=3//| n=4,acc=6//| n=5,acc=10//| n=6,acc=15//| res0: Int = 15sum(x => x * x)(1)(5) //> n=1,acc=0//| n=2,acc=1//| n=3,acc=5//| n=4,acc=14//| n=5,acc=30//| n=6,acc=55//| res1: Int = 55sum(x => x * x * x)(1)(5) //> n=1,acc=0//| n=2,acc=1//| n=3,acc=9//| n=4,acc=36//| n=5,acc=100//| n=6,acc=225//| res2: Int = 225val square = sum(x => x * x)_ //> square : Int => (Int => Int) = TestScala$$$Lambda$13/757108857@6bdf28bbsquare(1)(5) //> n=1,acc=0//| n=2,acc=1//| n=3,acc=5//| n=4,acc=14//| n=5,acc=30//| n=6,acc=55//| res3: Int = 55
转载于:https://www.cnblogs.com/anliven/p/10041890.html
Scala - 快速学习08 - 函数式编程:高阶函数相关推荐
- python学习——函数式编程——高阶函数
python学习--函数式编程--高阶函数 函数式编程(高阶函数):1:map && reduce; 2 : filter; 3: sorted; ------------------ ...
- 【一天时间|JavaScript进阶】函数式编程高阶函数的应用
一天时间系列文章是博主精心整理的面试热点问题和难点问题,吸收了大量的技术博客与面试文章,总结多年的面试经历,带你快速并高效地审视前端面试知识.直击技术痛点,主动出击,精密打击,这才是面试拿到高薪的秘诀 ...
- Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)...啊啊啊...
函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计 ...
- python3_函数_形参调用方式 / 不定长参数 / 函数返回值 / 变量作用域 / 匿名函数 / 递归调用 / 函数式编程 / 高阶函数 / gobal和nonlocal关键字 / 内置函数
1.形参的调用方式 1. 位置参数调用 2. 关键词参数调用 原则: 关键词参数调用不能写在位置参数调用的前边 def test1(name, age):print("name:" ...
- 函数式编程 --- 高阶函数
含义: 高阶函数全称 (Higher-order function) 1.可以把函数作为参数传递给另一个函数 2.可以把函数作为另一个函数的返回结果 意义:高阶函数是用来抽象通用的问题:抽象可以帮我们 ...
- Scala深入学习之函数式编程
目录 一.函数式编程 二.高阶函数 三.闭包和柯里化 一.函数式编程 示例代码: package matchDemo.function/*** @author : 蔡政洁* @email :caizh ...
- scala简明教程:偏函数、高阶函数、Future异步编程、隐式转换
高阶函数和匿名函数的使用:
- 函数式编程4-高阶函数
以其他函数作为参数的函数 本章的所有代码,均在github.com/antgod/func- 关于传递函数的思考 max 在很多编程语言的核心库,都包含一个叫做max的函数.包括underscore也 ...
- Python编程 高阶函数使用技巧
在坚持的初期,坚持本身比坚持的事情更重要.也许,生活的意义并不在于实现了怎样伟大的梦想,而是在于自己全身心地投入,让每一天都成为梦想的一部分.只要是能确定带给自己价值感的事情,去做就好.时间在流逝,每 ...
最新文章
- 算法学习——递推之猴子爬山
- 06_一对一和一对多
- [转载]浅析jQuery框架与构造对象
- Python 中的*args和**kwargs
- python顺序结构有一个入口_高楼万丈平地起,基础要打牢!Python获取类的层次结构和继承顺序...
- 20应用统计考研复试要点(part7)--统计学
- mybatis generator修改默认生成的sql模板
- USACO 2006 Open, Problem. The Country Fair 动态规划
- 使用数组操作解码YOLO Core ML对象检测(三)
- HDU 4927 大数运算
- 读《世界是数字的》笔记
- orm框架设计、分析与开发
- Cinema 4D* 中令人惊叹的体积效果
- c 语言编程怎样弄循环语句,C 语言循环语句
- eda交通灯控制器波形输入_【EDA课程设计】基于VHDL十字路口交通灯控制电路
- http_load压力测试步骤
- git 强制拉取最新代码
- html5普通文本框代码,html 文本框代码
- 根据出生日期判断星座
- mysql8.0字符集排序规则_MySQL 的字符集与排序规则
热门文章
- Winform中使用NPOI导出Excel时XSSFWorkbook wb = new XSSFWorkbook()报错
- Docker Compose部署GitLab服务,搭建自己的代码托管平台(图文教程)
- Winform中在FastReport的PreviewControl预览控件中对report控件模板中控件值进行修改
- Input为number类型maxlength不好使,用js轻松解决
- 安装Scrapy时:Microsoft Visual C++ 9.0 is required
- weblogic从入门到起飞(nodemanager)(五)
- cx+oracle+sql含中文,sql 判断字段值是是否包含中文字符
- 亚马逊专家课 | 数据体系+用户画像+商品画像系列课(立省 299 元)
- CSS3常用动画总结
- 人脸识别可以分辨同性恋?论科技研发和伦理道德之间的矛盾