泛函编程(3)-认识Scala和泛函编程
接着昨天的文章,再示范一个稍微复杂一点的尾递归tail recursion例子:计算第n个Fibonacci数。Fibonacci数第一、第二个数值分别是0,1,按顺序后面的数值是前面两个数的加合。例如:0,1,1,2,3,5...
def fib(n: Int): Int = {
@annotation.tailrec
def go(cnt: Int, prev: Int, cur: Int): Int = cnt match {
case m if (m < 0 ) => sys.error("Negative Number Not Allowed!")
case 0 => prev
case c => go(cnt-1,cur, prev + cur)
}
go(n,0,1)
} //> fib: (n: Int)Int
fib(5) //> res52: Int = 5
首先,尾递归是指一个递归函数最后一个语句独立引用了自己。在以上的例子里 go(cnt-1,cur,prev + cur)是最后一条没有增加任何运算的独立语句。我们可以试着约化:
fib(5)
go(5,0,1)
go(4,1,0+1) = go(4,1,1)
go(3,(0+1),1+(0+1)) = go(3,1,2)
go(2,1+(0+1),(0+1)+(1+(0+1))) = go(2,2,3)
go(1,(0+1)+(1+(0+1)),(1+(0+1))+(0+1)+(1+(0+1))) = go(1,3,5)
go(0,5,8) => 5
正是我们预期的答案。
Scala的函数(function)还是值得提的。函数可以当作标准的对象使用:可以当作另一个函数的输入参数或者结果值。接受函数作为输入参数或者返回另一函数作为结果的函数被称之为高阶函数(high order function)。在Scala编程里匿名函数(anonymous function or lamda function)或函数文本(function literal)的使用也很普遍。用书上的代码样例来示范:
def formatResult(name: String, n: Int, f: Int => Int) = {
val msg = "The %s of %d is %d."
msg.format(n, f(n))
}
注意formatResult是一个高阶函数,因为它接受一个函数f作为输入参数。这里 Int => Int 是一个类声明,是个函数的类型。看看高阶函数和匿名函数是怎么使用的:
def main(args: Array[String]): Unit = {
println(formatResult("absolute value", -42, abs))
println(formatResult("factorial", 7, factorial))
println(formatResult("increment", 7, (x: Int) => x + 1))
println(formatResult("increment2", 7, (x) => x + 1))
println(formatResult("increment3", 7, x => x + 1))
println(formatResult("increment4", 7, _ + 1))
println(formatResult("increment5", 7, x => { val r = x + 1; r }))
}
传入函数formatResult的输入参数f可以是一个普通的函数如factorial,abs。也可用函数文本,只要它的类型是Int => Int就可以了。以上匿名函数的各种表述形式可以参考一下Scala语言教程。
泛函编程(3)-认识Scala和泛函编程的更多相关文章
- 泛函编程(27)-泛函编程模式-Monad Transformer
经过了一段时间的学习,我们了解了一系列泛函数据类型.我们知道,在所有编程语言中,数据类型是支持软件编程的基础.同样,泛函数据类型Foldable,Monoid,Functor,Applicative, ...
- 备份-泛函编程(23)-泛函数据类型-Monad
泛函编程(23)-泛函数据类型-Monad http://www.cnblogs.com/tiger-xc/p/4461807.html https://blog.csdn.net/samsai100 ...
- scala的面向对象编程
1.scala的简单编程 2.构造方法 辅助构造函数是在主构造函数没有的情况下,执行的构造函数. 3.object的介绍 4.半生类和半生对象 5.半生的案例程序(半生类可以调用半生) 6.apply ...
- Scala链式编程内幕
package big.data.analyse.scala /** * 链式编程原理 * Created by zhen on 2018/12/16. */ class Computer{def c ...
- Scala界面事件处理编程实战详解.
今天学习了一个Scala界面事件处理编程,让我们从代码出发. import scala.swing._import scala.swing.event._ object GUI_Panel exten ...
- 第70讲:Scala界面GUI编程实战详解
今天又学习了王家林老师的scala学习讲座第70讲,关于scala的界面编程,让我们来初步学习一下scala中界面编程的过程. 信息来源于 DT大数据梦工厂微信公众账号:DT_Spark 关注微信账号 ...
- Python黑帽编程2.8 套接字编程
Python黑帽编程2.8 套接字编程 套接字编程在本系列教程中地位并不是很突出,但是我们观察网络应用,绝大多数都是基于Socket来做的,哪怕是绝大多数的木马程序也是如此.官方关于socket编程的 ...
- 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
- C#编程总结(六)异步编程
C#编程总结(六)异步编程 1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某 ...
- 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换
[源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...
随机推荐
- Atitit 图像处理知识点 知识体系 知识图谱v2
Atitit 图像处理知识点 知识体系 知识图谱v2 霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法.主要用来从图像 ...
- Atitit 基于meta的orm,提升加速数据库相关应用的开发
Atitit 基于meta的orm,提升加速数据库相关应用的开发 1.1. Overview概论1 1.2. Function & Feature功能特性1 1.2.1. meta api2 ...
- iOS开发——高级技术精选OC篇&Runtime之字典转模型实战
Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...
- angularjs可交互的directive
angularjs可交互的directive http://jsfiddle.net/revolunet/s4gm6/ directive开发上手练手,以注释的方式说明 html <body n ...
- 开始使用MarkDown写博客
MarkDown 标题 #h1 ##h2 ###h3 h1 h2 h3 代码段 代码段缩进4个空格即可,如下: <div class="form-group"> < ...
- winform 程序制作自己的数字签名(续)
在上一篇文章<winform 程序制作自己的数字签名>中我们已经可以得到我们程序定制的数字签名了,但是比较讨厌的是每次编译之后,数字签名需要重新手动添加. 我们需要的是在程序编译时自动添加 ...
- WCF传输1-你是否使用过压缩或Json序列化?
1.当遇到需要传输大量数据时,怎么样传输数据? 2.压缩数据有哪几种常见的方式? 问题1解答:通过压缩来传输数据 问题2解答: (1)WCF自带的压缩方式 (2)自定义WCF binding进行压缩 ...
- CentOS安装运行NodeJS框架Express
安装依赖包 yum -y install gcc make gcc-c++ openssl-devel wget 下载/解压NodeJs wget http://nodejs.org/dist/v0. ...
- PHP的学习--连接MySQL的三种方式
记录一下PHP连接MySQL的三种方式. 先mock一下数据,可以执行一下sql. /*创建数据库*/ CREATE DATABASE IF NOT EXISTS `test`; /*选择数据库*/ ...
- android 处理302地址
最近项目中需要用到重定向下载,所以找了很多的方法都不合适.因为下载的链接并非单纯的地址,而是需要多次转发的, 在下载的时候用的是URL来打开数据流.但是多次测试并不能对多次跳转的链接打开请求.对于30 ...