泛函编程(3)-认识Scala和泛函编程

接着昨天的文章,再示范一个稍微复杂一点的尾递归tail recursion例子:计算第n个Fibonacci数。Fibonacci数第一、第二个数值分别是0,1,按顺序后面的数值是前面两个数的加合。例如:0,1,1,2,3,5...

 1 def fib(n: Int): Int = {
 2     @annotation.tailrec
 3       def go(cnt: Int, prev: Int, cur: Int): Int = cnt match {
 4         case m if (m < 0 ) => sys.error("Negative Number Not Allowed!")
 5         case 0 => prev
 6         case c => go(cnt-1,cur, prev + cur)
 7       }
 8       go(n,0,1)
 9   }                                               //> fib: (n: Int)Int
10   fib(5)                                          //> res52: Int = 5

首先,尾递归是指一个递归函数最后一个语句独立引用了自己。在以上的例子里 go(cnt-1,cur,prev + cur)是最后一条没有增加任何运算的独立语句。我们可以试着约化:

1 fib(5)
2   go(5,0,1)
3   go(4,1,0+1)                                         = go(4,1,1)
4   go(3,(0+1),1+(0+1))                                 = go(3,1,2)
5   go(2,1+(0+1),(0+1)+(1+(0+1)))                       = go(2,2,3)
6   go(1,(0+1)+(1+(0+1)),(1+(0+1))+(0+1)+(1+(0+1)))    = go(1,3,5)
7   go(0,5,8) => 5

正是我们预期的答案。

Scala的函数(function)还是值得提的。函数可以当作标准的对象使用:可以当作另一个函数的输入参数或者结果值。接受函数作为输入参数或者返回另一函数作为结果的函数被称之为高阶函数(high order function)。在Scala编程里匿名函数(anonymous function or lamda function)或函数文本(function literal)的使用也很普遍。用书上的代码样例来示范:

1 def formatResult(name: String, n: Int, f: Int => Int) = {
2   val msg = "The %s of %d is %d."
3   msg.format(n, f(n))
4 }

注意formatResult是一个高阶函数,因为它接受一个函数f作为输入参数。这里 Int => Int 是一个类声明,是个函数的类型。看看高阶函数和匿名函数是怎么使用的:

1 def main(args: Array[String]): Unit = {
2   println(formatResult("absolute value", -42, abs))
3   println(formatResult("factorial", 7, factorial))
4   println(formatResult("increment", 7, (x: Int) => x + 1))
5   println(formatResult("increment2", 7, (x) => x + 1))
6   println(formatResult("increment3", 7, x => x + 1))
7   println(formatResult("increment4", 7, _ + 1))
8   println(formatResult("increment5", 7, x => { val r = x + 1; r }))
9 }

传入函数formatResult的输入参数f可以是一个普通的函数如factorial,abs。也可用函数文本,只要它的类型是Int => Int就可以了。以上匿名函数的各种表述形式可以参考一下Scala语言教程。

时间: 2024-10-02 19:06:11

泛函编程(3)-认识Scala和泛函编程的相关文章

泛函编程(27)-泛函编程模式-Monad Transformer

经过了一段时间的学习,我们了解了一系列泛函数据类型.我们知道,在所有编程语言中,数据类型是支持软件编程的基础.同样,泛函数据类型Foldable,Monoid,Functor,Applicative,Traversable,Monad也是我们将来进入实际泛函编程的必需.在前面对这些数据类型的探讨中我们发现: 1.Monoid的主要用途是在进行折叠(Foldable)算法时对可折叠结构内元素进行函数施用(function application). 2.Functor可以对任何高阶数据类型F[_]

泛函编程(15)-泛函状态-随意数产生器

对于OOP程序员来说,泛函状态变迁(functional state transition)是一个陌生的课题.泛函状态变迁是通过泛函状态数据类型(functional state)来实现的.State是一个出现在泛函编程里的类型(type).与其它数据类型一样,State同样需要自身的一套泛函操作函数和组合函数(combinators),我们将在以下章节中讨论有关State数据类型的设计方案. 在正式介绍State类型前,我们先从随意数产生器(RNG: Random Number Generat

scala范函编程是怎样被选中的

现在计算机技术发展现象是:无论硬件技术如何发展都满足不了软件需求:无论处理器变得能跑多快,都无法满足软件对计算能力的需要.按照摩尔定律(Moore's Law)处理器(CPU)每平方面积上包含的半导体晶体管数量每18个月将会增加一倍.发展到现在,所有CPU厂商都再也无法按照摩尔定律在一定面积上成倍增加半导体了,大家也都只能朝着增加CPU内核数量上努力了.多核CPU已然成为现代计算机技术发展趋势.现代软件对计算能力的需求暴增主要归咎于现代社会中数据应用的普及和泛滥.这种数据量级单凭增加处理器和存储

第70讲:Scala界面GUI编程实战详解

今天又学习了王家林老师的scala学习讲座第70讲,关于scala的界面编程,让我们来初步学习一下scala中界面编程的过程. 信息来源于 DT大数据梦工厂微信公众账号:DT_Spark 关注微信账号,获取更多关于王家林老师的课程内容 王老师QQ:1740415547 微信号:18610086859 首先,scala中的界面编程是封装和改进了java的界面编程的swing库,当然我们在用scala进行界面编程的时候,要先引入此类库,下面让我们从代码实战出发. import scala.swing

Scala界面事件处理编程实战详解.

今天学习了一个Scala界面事件处理编程,让我们从代码出发. import scala.swing._import scala.swing.event._ object GUI_Panel extends SimpleSwingApplication{  def top = new MainFrame{//重写框架    title = "second GUI"//界面名称    val button = new Button{//定义按钮      text = "scal

学习进度十三(Scala独立应用编程)

环境如下: Hadoop 2.6.0以上 java JDK 1.7以上 Spark 3.0.0-preview2 一.Scala独立应用编程 1.安装sbt sbt是一款Spark用来对scala编写程序进行打包的工具,这里简单介绍sbt的安装过程,感兴趣的读者可以参考官网资料了解更多关于sbt的内容.Spark 中没有自带 sbt,这里直接给出sbt-launch.jar的下载地址,直接点击下载即可.我们选择安装在 /usr/local/sbt 中: sudo mkdir /usr/local

网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服务器进程B1同时为客户进程A1.A2和B2提供服务. Socket概述 ①   所谓Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过“套接字”向网络发出请求或者应答网络请求. ②   Socket是连接运行在网络上的两个程序间的双向通信的端点. ③  

有人认为“中文编程”是解决中国程序员编程效率的秘密武器,请问它是一个“银弹”么?

有人认为“中文编程”是解决中国程序员编程效率的秘密武器,请问它是一个“银弹”么?首先,百度给出“银弹”是这样的解释:能杀死狼人的利器 在古老的传说里.狼人是不死的.想要杀死狼人有几种方法: 1.像杀死吸血鬼那样用木桩钉住狼人的心脏. 2.将月光遮住 3.用银子做的子弹射穿狼人的心脏或头 当然现实中是没有狼人的.但现实中确实有银弹这个东西.而其意义也类似于能杀死狼人的最好办法.现实中的狼人可以是一个棘手的项目,或者一件不可能的事.而“银弹”就是指能解决这些事的方法,或者技术手段. 我不认中文编程是

2.有人认为,“中文编程”是解决中国程序员编程效率的秘密武器,请问它是一个“银弹”么?

银色子弹(英文:Silver Bullet),或者称“银弹”“银质子弹”,指由纯银质或镀银的子弹.在欧洲民间传说及19世纪以来哥特小说风潮的影响下,银色子弹往往被描绘成具有驱魔功效的武器,是针对狼人等超自然怪物的特效武器.后来银色子弹常被用做致命武器的代言词.被比喻为具有极端有效性的解决方法,作为杀手锏[1]  .最强杀招.王牌等的代称. IBM大型机之父佛瑞德·布鲁克斯(Frederick P. Brooks, Jr.)在1986年发表的一篇关于软件工程的经典论文,便以<没有银弹:软件工程的本

C#编程总结(六)异步编程

C#编程总结(六)异步编程 1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行. 2.同步与异步的区别 同步(Synchronous):在执行某个操作时,应用程序必须等待该操作执行完成后才能继续执行. 异步(Asynchronous):在执行某个操作时,应用程序可在异步操作执行时继续执行.实质:异步操作,启动了新的线程,主线程