继续领悟函数式:Scala指令式风格代码的重构

开发 后端
本文节选自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻译的《Programming in Scala》的第七章。Scala是一种针对 JVM 将函数和面向对象技术组合在一起的编程语言。

为了帮助你在函数式风格上获得更多的领悟,本节我们将重构代码7.18中以指令式风格打印乘法表的方式。我们的函数式替代品展示在代码7.19中。

51CTO编辑推荐:Scala编程语言专题

代码7.18中的代码在两个方面显示出了指令式风格。首先,调用printMultiTable有副作用:在标准输出上打印乘法表。代码7.19中,我们重构了函数,让它把乘法表作为字串返回。由于函数不再执行打印,我们把它重命名为multiTable。正如前面提到过的,没有副作用的函数的一个优点是它们很容易进行单元测试。要测试printMultiTable,你需要重定义print和println从而能够检查输出的正确性。测试multiTable就简单多了,只要检查结果即可。

  1. // 以序列形式返回一行乘法表  
  2. def makeRowSeq(row: Int) =  
  3.  for (col < - 1 to 10) yield {  
  4.   val prod = (row * col).toString  
  5.   val padding = " " * (4 - prod.length)  
  6.   padding + prod  
  7.  }  
  8. // 以字串形式返回一行乘法表  
  9. def makeRow(row: Int) = makeRowSeq(row).mkString  
  10. // 以字串形式返回乘法表,每行记录占一行字串  
  11. def multiTable() = {  
  12.  val tableSeq = // 行记录字串的序列  
  13.   for (row < - 1 to 10)  
  14.    yield makeRow(row)  
  15.  tableSeq.mkString("\n")  
  16. }  
代码 7.19 创建乘法表的函数式方法

printMultiTable里另一个揭露其指令式风格的信号来自于它的while循环和var。与之相对,multiTable函数使用了val,for表达式,帮助函数:helper function,并调用了mkString。

我们提炼出两个帮助函数,makeRow和makeRowSeq,使代码容易阅读。函数makeRowSeq使用for表达式从1到10枚举列数。这个for函数体计算行和列的乘积,决定乘积前占位的空格,并生成由占位空格,乘积字串叠加成的结果。for表达式的结果是一个包含了这些生成字串作为元素的序列(scala.Seq的某个子类)。另一个帮助函数,makeRow,仅仅调用了makeRowSeq返回结果的mkString函数。叠加序列中的字串把它们作为一个字串返回。

multiTable方法首先使用一个for表达式的结果初始化tableSeq,这个for表达式从1到10枚举行数,对每行调用makeRow获得该行的字串。因为字串前缀yield关键字,所以表达式的结果就是行字串的序列。现在仅剩下的工作就是把字串序列转变为单一字串。mkString的调用完成这个工作,并且由于我们传递进去"\n",因此每个字串结尾插入了换行符。如果把multiTable返回的字串传递给println,你将看到与调用printMultiTable所生成的同样的输出结果。

【相关阅读】

  1. 学习Scala的变量范围
  2. Scala:match表达式、break和continue
  3. 学习Scala:使用try-catch表达式处理异常
  4. Scala中的for表达式:枚举的“瑞士军刀”
  5. Scala中的if表达式和while循环

责任编辑:book05 来源: Artima
相关推荐

2009-06-09 13:18:56

Scala函数式命令式

2009-07-09 00:25:00

Scala函数式

2010-01-28 14:51:24

Scala后函数式

2009-12-11 10:44:00

Scala讲座函数 scala

2019-09-09 11:40:18

编程函数开发

2010-03-11 10:34:22

Scala

2009-07-08 16:10:24

Scala简介面向对象函数式

2009-09-27 15:29:00

Scala讲座面向对象Scala

2009-09-27 15:23:00

Scala讲座函数式编程Scala

2011-06-02 09:47:11

C语言重构

2010-07-07 13:11:20

ScalaF#C#

2010-07-09 14:12:00

ScalaF#C#

2020-12-17 07:59:46

声明式代码命令式代码代码

2016-10-11 13:32:50

函数式TypeScriptJavascript

2009-07-21 13:54:55

Scala重载方法隐式转换

2012-03-14 10:09:51

ibmdw

2015-09-01 15:00:50

七牛许式伟

2023-07-10 09:39:02

lambdaPython语言

2013-09-09 09:41:34

2016-09-30 09:43:17

JavascriptTypeScript函数式编程
点赞
收藏

51CTO技术栈公众号