scala入门之识别函数式风格
博客专区 > 柳哥 的博客 > 博客详情
scala入门之识别函数式风格
柳哥 发表于4年前
scala入门之识别函数式风格
  • 发表于 4年前
  • 阅读 173
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

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不是只能使用函数式风格编程的纯函数式语言。它是这两种风格的混合式语言。甚至有时你会发现指令式风格能更有效地解决手中的问题,那就使用指令式风格,别犹豫

标签: scala
共有 人打赏支持
粉丝 200
博文 394
码字总数 347782
×
柳哥
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: