scala是一种函数式编程风格的语言,除了常见的if......else  ,for ,while等传统的流程控制结构,也可以自定义流程控制的控制结构。

再了解scala如何实现编写新的流程结构,我们了解一下头等函数的概念;

scala的函数是头等函数(first-class function).你不仅可以定义和调用函数。还可以把他们写成匿名的字面量(Iiteral),并把他们作为值(value)传递。

在拥有头等函数的语言中,即使语言的语法是固定的,你也可以有效地制作新的控制流程结构,可以使用创建带函数参数的方法来做到这点;另一种方法是

使用用花括号代替小括号的机制。

(一)使用创建带函数参数的方法来编写新的控制结构

下面是"双倍"控制结构的实现,能够重复一个操作两次并返回结果:

def twice(op: Double => Double,x: Double) = op(op(x))

#调用方法
twice(_ + 1,5)

twice函数解析:该函数有2两个参数,
第一个参数是function,作用是把一个double转化成另一个double。
第二个参数double类型的数字。
op(x)的意思是调用op对象的apply() 方法,由于op是函数值对象,所以op(x)的意思是,将x应用为op函数的参数。

所以 twice(_ + 1,5) 的返回值是 7.

当你在代码中发现,有个重复的控制模式时,就可以考虑把这些重复的控制模式实现成一个新的控制结构。

文件操作是的流程是:打开一个资源,对它进行操作,关闭资源。这是一个经常使用的代码模式。我们可以新建

一个控制结构来实现这个功能。

    /**
* withPrintWriter 方法有两个参数:
* 第一个参数的值:file对象。
* 第一个参数的值:function类型的对象,其中function的参数是PrintWriter,返回值是Unit。
*
*/
def withPrintWriter(file: File,op: PrintWriter => Unit){
val writer = new PrintWriter(file)
try{
op(writer)
}finally{
writer.close()
println("closed the print writer.")
}
}
  //调用withPrintWriter方法
withPrintWriter(new File("D:/loader.log"), writer => {println("write a time str to file.");writer.print(new java.util.Date)})

withPrintWriter方法调用过程分析,

withPrintWriter(new File("D:/loader.log"), writer => {println("write a time str to file.");writer.print(new java.util.Date)})
第一个参数的值:file对象。
第一个参数的值:function类型的对象,该function的功能是将一个时间戳写入到这个文件中,并在写之前打印一条提示日志。
使用withPrintWriter的好处是:withPrintWriter并非客户代码,可以确保文件在结尾被关闭;
因此客户忘记关闭文件是不可能的。这个技巧被称为借贷模式(loan parttern)。
拿withPrintWriter来讲:withPrintWriter打开了资源并"贷出"给函数, withPrintWriter把printWriter借给
函数op;当函数op完成时,它发出信号说明它不再需要 "借"的资源PrintWriter,于是资源在finally块中被关闭,

以确信其确实被关闭,而忽略函数是正常结束返回还是抛出了异常。

(二)使用用花括号代替小括号的机制实现

为了让客户代码看上去更像内建控制结构的另一种方式是使用花括号代替小括号包围参数列表。
scala的任何方法调用,如果你确实只传入一个参数,就可以选择使用花括号代替小括号包围参数。

例如如下代码:

      println("hello,world") ////如果有一个参数,可以用花括号代替小括号包围参数。
println{"hello,world"} val g = "Hello,world!"
g.substring(7,9)
// g.substring{7,9} //如果有两个参数,就不能用花括号代替小括号包围参数,会报出编译错误

为了使用{}替换小括号,使用柯里化重新定义前一函数withPrintWriter,源码如下:

  /**
* 使用柯里化重新定义函数。
* scala在传入一个参数时,可以用花括号代替小括号的机制:
* 这个机制的目的是让客户端程序能写出包围在花括号内的函数字面量;这可以让方法调用感觉更像控制抽象。
*/
def withPrintWriter2(file: File)(op: PrintWriter => Unit) = {
val writer = new PrintWriter(file)
try{
op(writer)
}finally{
writer.close()
}
} //调用该函数。
//调用柯里化的withPrintWriter2方法,第一函数参数以小括号包围参数,第二个一花括号包围参数(参数是函数字面量)。
//这种方法调用看起来是不是比较赏心悦目啊!
withPrintWriter2(new File("D:/kafka_loader.log")){
writer => writer.print(new java.util.Date)
}
//当然也可以都用小括号,或者都用大括号,也是没有问题的?看个人喜好了,但是代码就有点怪异!
withPrintWriter2(new File("D:/kafka_loader.log"))(
writer => writer.print(new java.util.Date)
)
withPrintWriter2{new File("D:/kafka_loader.log")}{
writer => writer.print(new java.util.Date)
} // 简化一下调用方法
val file = new File("D:/kafka_loader.log")
val func = (writer: PrintWriter) => writer.print(new java.util.Date)
withPrintWriter2(file){func} //都是合法的哦,这种更像控制抽象。
withPrintWriter2(file)(func) //都是合法的哦
withPrintWriter2{file}{func} //都是合法的哦
withPrintWriter2{file}(func) //都是合法的哦

scala中如何编写自定义的流程控制结构的更多相关文章

  1. Programming In Scala笔记-第七章、Scala中的控制结构

    所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...

  2. 在 WF 4 中编写自定义控制流活动

    在 WF 4 中编写自定义控制流活动 Leon Welicki 控制流是指组织和执行程序中各个指令的方法. 在 Windows Workflow Foundation 4 (WF 4) 中,控制流活动 ...

  3. Scala中的流程控制

    一.分支控制if-else //Scala中if-else语句中,代码块内最后一句代码就是返回值 def main(args: Array[String]): Unit = { var age:Int ...

  4. (八)MySQL事务、视图、变量、存储过程、函数、流程控制结构

    补充:增删查改语句在数据库中基本通用,但这篇博客的内容基本是MySQL区别于其它数据库管理系统的知识,也要认真学习. 一.事务 1.含义:在MySQL中,可以通过创建事务来解决一些问题. 2.语法: ...

  5. django “如何”系列4:如何编写自定义模板标签和过滤器

    django的模板系统自带了一系列的内建标签和过滤器,一般情况下可以满足你的要求,如果觉得需更精准的模板标签或者过滤器,你可以自己编写模板标签和过滤器,然后使用{% load %}标签使用他们. 代码 ...

  6. Scala学习(五)---Scala中的类

    Scala中的类 摘要: 在本篇中,你将会学习如何用Scala实现类.如果你了解Java或C++中的类,你不会觉得这有多难,并且你会很享受Scala更加精简的表示法带来的便利.本篇的要点包括: 1. ...

  7. 在Scala中免费验证

    优锐课带你详细了解如何在Scala中实施免费的monad验证.抽丝剥茧,细说架构那些事! 由于业务数据的复杂性,已经在数据验证上花费了很多精力.在Scala中,提出了使用应用程序进行验证的方法,并被广 ...

  8. Scala中的函数高级使用

    1.偏函数 1.基本介绍 在对符合某个条件,而不是所有情况进行逻辑操作时,使用偏函数是一个不错的选择 将包在大括号内的一组case语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范 ...

  9. 【持续集成】[Jenkins]Job中如何传递自定义变量

    [Jenkins]Job中如何传递自定义变量 来自dweiwei   2015-06-27 18:37:19|  分类: 自动化测试 |举报 |字号大中小 订阅 用微信  “扫一扫” 将文章分享到朋友 ...

随机推荐

  1. PHP获取不了React Native Fecth参数的解决办法是怎么样呢?

    fetch('https://mywebsite.com/endpoint/', { method: 'POST',headers: {'Accept': 'application/json','Co ...

  2. 15、Jdbc的优化(BeanUtils组件)

    Jdbc的优化! BeanUtils组件 自定义一个持久层的框架 DbUtils组件 案例优化 1. BeanUtils组件 1.1    简介 程序中对javabean的操作很频繁, 所以apach ...

  3. Python升级Yum不能使用解决

    1.系统版本 [root@vm10-254-206-95 ~]# cat /etc/issue CentOS release 6.4 (Final) Kernel \r on an \m 2.系统默认 ...

  4. Jetty 嵌入式开发(实例)

    我尝试了jetty几个版本,类的使用有些差异,在此记录下jettyVersion = 9.0.2.v20130417 的部分实例 maven 依赖及配置: <properties> < ...

  5. PHP的Socket通信之UDP篇

    1.创建一简单的UDP服务器 //服务器信息 $server = 'udp://127.0.0.1:9998'; //消息结束符号 $msg_eof = "\n"; $socket ...

  6. Android处理图片OOM的若干方法小结 (推荐)

    众所周知,每个Android应用程序在运行时都有一定的内存限制,限制大小一般为16MB或24MB(视平台而定).因此在开发应用时需要特别关注自身的内存使用量,而一般最耗内存量的资源,一般是图片.音频文 ...

  7. YTU 2986: 删除区间内的元素(线性表)

    2986: 删除区间内的元素(线性表) 时间限制: 1 Sec  内存限制: 2 MB 提交: 8  解决: 3 题目描述 若一个线性表L采用顺序存储结构,其中元素都为整数.设计一个算法,删除元素值在 ...

  8. jQuery.validator 详解

    jQuery.validator 详解二 前言:上一篇详细的介绍了jQuery.validator( 版本v1.13.0 )的验证规则,这一篇重点讲述它的源码结构,及如何来对元素进行验证,错误消息提示 ...

  9. Animator角色重复受击播放问题

    需要指定开始时间参数,否则Animator会默认当前已经在播放这个动画而忽略掉 CrossFade一样 gif: public class AnimatorDebug : MonoBehaviour ...

  10. CSUFT 1005 Coffin Tiles

    1005: Coffin Tiles Time Limit: 1 Sec      Memory Limit: 128 MB Submit: 2      Solved: 2 Description ...