文档章节

scala入门之识别函数式风格

柳哥
 柳哥
发布于 2014/06/05 20:05
字数 1088
阅读 177
收藏 1

scala允许指令式的编程风格,但是鼓励采用函数式的风格。如果你是从指令式的背景转到scala来的-----例如,如果你是Java程序员------那么学习scala将面对的主要挑战就是理解怎样用函数式的风格编程。我们的首要工作是识别这两种风格在代码上的差异。大致可以说,如果代码包含了任何 var 变量,那它可能就是指令式的风格如果代码根本就没有 var ------就是说仅仅包含 val ------那它或许是函数式的风格。因此向函数式风格转变的方式之一,就是尝试不用任何 var 编程。
如果你来自于指令式的语言环境,如:Java、C++、或者C#,你或许认为 var 是很正统的而 val 比较特殊。相反,如果你来自于函数式语言环境,如:Haskell、OCamel或Erlang,或许你会认为 val 很正常而对 var 就有一种抵触情绪了。然而在scala看来,val 和 var 只不过是工具箱里两种不同的工具。它们都很有用,没有一个天性邪恶。scala鼓励你学习 val ,但最终做到“物尽其用”的原则。
指令式风格的例子:

def printArgs(args:Array[String]):Unit = { 
    var i = 0
    while(i < args.length){ 
        println(args(i)) 
        i += 1
    } 
}

你可以通过去掉 var 的办法把这个代码变得更函数式风格,如例:

def printArgs(args:Array[String]):Unit = { 
    for(arg <- args) 
        println(arg) 
}

或者:

def printArgs(args:Array[String]):Unit = { 
    args.foreach(println) 
}

这个例子说明了减少使用 var 的一个好处。重构后(更函数式)的代码比原来(更指令式)的代码更简洁、明白,也更少有机会犯错。scala鼓励函数式风格的原因,实际上也就是因为函数式风格可以帮助你写出更易读懂,同样也是更不易犯错的代码。
当然,这段代码仍有修改的余地。重构后的printArgs方法并不是纯函数式的,因为它有副作用(副作用?计算并返回结果之外的其它行为??)------本例中的副作用就是打印到标准输出流。识别函数是否有副作用的地方就在于其结果类型是否为Unit。如果某个函数不返回任何有用的值,也就是说如果返回类型为Unit,那么这个函数唯一能产生的作用就只能是完成某种副作用。而函数风格的方式应该是定义对需打印的arg进行格式化的方法,不过仅返回格式化之后的字符串,如例:

def formatArgs(args:Array[String]) = args.mkString(“\n”);

现在才是真正函数式风格的了:完全没有副作用或 var 的 mkString方法,能在任何可枚举的集合类型(包括数组,列表,集和映射)上调用,返回由每个数组元素调用mkString,并把传入字符串做分隔符组成的字符串。当然,这个函数并不像printArgs方法那样能够实际完成打印输出,但可以简单地把它的结果传递给println来实现:

println(formatArgs(args));

每个有用的程序都会有某种形式的副作用,否则就不可能向程序之外提供什么有价值的东西。我们提倡无副作用的方法是为了鼓励你尽量设计出没有副作用代码的程序。这种方式的好处之一是可以有助于你的程序更容易测试。举例来说,要测试前面给出的任何一个有副作用的printArgs方法,你将需要重定义println,捕获传递给它的输出,再检查结果。相反,对于formatArgs来说你可以直接检查它的返回结果:

val res = formatArgs(Array(“zero”,“one”,“two”);
assert(res == “zero\none\ntwo”);

不过还是要牢记:不管是var还是副作用都不是天生邪恶的。Scala不是只能使用函数式风格编程的纯函数式语言。它是这两种风格的混合式语言。甚至有时你会发现指令式风格能更有效地解决手中的问题,那就使用指令式风格,别犹豫

© 著作权归作者所有

共有 人打赏支持
柳哥
粉丝 205
博文 405
码字总数 347782
作品 0
杭州
技术主管
私信 提问
Scala入门-大数据云计算下的开发语言

Scala编程语言抓住了很多开发者的眼球。如果你粗略浏览Scala的网站,你会觉得Scala是一种纯粹的 面向对象编程语言,而又无缝地结合了命令式编程和 函数式编程风格。Christopher Diggins认为:...

liwei2000
06/30
0
0
Scala基础入门-1

首先需要Scala开发环境的搭建,网上自己找教程。 声明常量与变量 val foo = 0 // 常量var bar = 0 // 变量    在Scala中,更加鼓励使用val来进行声明,也就是推荐使用常量。在大部分时候不...

wei-spring
2015/11/08
0
0
总有你要的编程书单(GitHub )

目录 IDE IntelliJ IDEA 简体中文专题教程 MySQL 21分钟MySQL入门教程 MySQL索引背后的数据结构及算法原理 NoSQL Disque 使用教程 Neo4j .rb 中文資源 Redis 命令参考 Redis 设计与实现 The ...

汇智网
2017/11/22
0
0
free-programming-books-zh.md

语言无关MySQL NoSQL PostgreSQL Web WEB服务器 其它 函数式概念 分布式系统 在线教育 大数据 操作系统 数据库 智能系统 正则表达式 版本控制 程序员杂谈 管理和监控 编程艺术 编译原理 编辑...

银月光海
2016/05/20
70
0
Scala 技术周刊 | 第 22 期

这里有最新的 Scala 社区动态、技术博文。 微信搜索 「scalacool」关注我们,及时获取最新资讯。 深度阅读 Status of the Collections Scala 集合重构进展 Akka 系列(十):Akka 集群之 Ak...

ScalaCool
2017/09/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

new Date() 在Safari下的 Invalid Date问题

问题复现 var timeStr = '2018-11-11 00:00:00';var time = new Date(timeStr);// error: Invalid Date... 在safari浏览器下,time为Invalid Date, 导致后面代码执行错误; 其他浏览器诸...

会写代码的husky
25分钟前
2
0
0009-如何升级Cloudera Manager和CDH

1.文档编写目的 本文档讲述如何升级Cloudera Manager和CDH,通过本文档,您将学习到以下知识: 1.如何对Cloudera Manager进行停机升级 2.如何对CDH进行停机升级 3.如何在不影响集群作业的情况...

Hadoop实操
35分钟前
1
0
vue2中引用 better-scroll的方法

文章主要介绍了vue2中引用better-scroll和使用 better-scroll的方法,使用时有三个要点及注意事项在文中给大家详细介绍 ,需要的朋友可以参考下 使用时有三个要点: 一:html部分 <div class...

前端攻城老湿
45分钟前
1
0
浅谈教你如何掌握Linux系统

linux能做什么?相信绝大数人都有这样的疑问。可以玩吃鸡吗?可以玩lol吗? 如果你是以娱乐的名义来评价linux的可用性,对不起,linux可能不适合你,因为linux是一个工具,他是教你聪明的,不...

linuxprobe16
52分钟前
1
0
java中线程池的生命周期

线程池生命周期包括: RUNNING:接收新的任务并处理队列中的任务 SHUTDOWN:不接收新的任务,但是处理队列中的任务 STOP:不接收新的任务,不处理队列中的任务,同时中断处理中的任务 TIDYING:所...

小刀爱编程
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部