用Scala实现一个简单的Python的上下文管理器
Posted 鸿的学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Scala实现一个简单的Python的上下文管理器相关的知识,希望对你有一定的参考价值。
上下文管理器是对try/finally模式的简化,保证一段代码运行完后执行某项操作,即使那段代码被中止了,也会执行指定的操作。在这篇文章将展现函数式编程的威力,用Scala写一个简单的上下文管理器。
简单介绍下Python的with,它是属于上下文管理器协议,使用__enter__和__exit__方法实现协议,在with语句运行之前会调用__enter__方法,结束之后调用__exit__方法。最常见的例子就是关闭文件对象,这次我们也要用Scala实现下面的语法。
with open('D:\\data.txt') as f:
data = f.read()
f.closed
Out[3]: True
在开始写之前,先了解下柯里化(Currying)的概念。柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数。先看看一个正常的oldSum函数:
scala> def oldSum(x:Int, y:Int) = x + y
oldSum: (x: Int, y: Int)Int
scala> oldSum(1,2)
res0: Int = 3
scala> def curriedSum(x:Int)(y:Int) = x + y
curriedSum: (x: Int)(y: Int)Int
scala> curriedSum(1)(2)
res1: Int = 3
curriedSum是柯里化函数,当在调用curriedSum时,实际上是连着做了两次的函数调用,可以理解为是一个嵌套函数:
scala> def first(x:Int) = (y:Int) => x + y
first: (x: Int)Int => Int
scala> val second = first(1)
second: Int => Int = <function1>
scala> second(2)
res3: Int = 3
虽然实现原理并不一致,但是可以这么理解柯里化的实现过程,并且也可以通过占位符(一个神奇的符号)去缓存第二个函数的使用。
scala> val onePlus = curriedSum(1)_
onePlus: Int => Int = <function1>
scala> onePlus(2)
res4: Int = 3
当了解柯里化后,回忆一下,前文提到了Scala里的函数是一等对象,函数本身是可以当作参数传给函数的:
scala> def twicePlus(plus:Int => Int, x:Int) = plus(plus(x))
twicePlus: (plus: Int => Int, x: Int)Int
scala> twicePlus(_+1,5)
res5: Int = 7
神奇的_符号又来了,_ + 1可以理解为(如果不是老手,_+1并没有下面的容易理解):
scala> val add=(x:Int) => x+ 1
add: Int => Int = <function1>
scala> twicePlus(add,5)
res6: Int = 7
plus:Int => Int,这里的含义是传入一个入参为Int类型的值,返回值是Int类型值函数。除了圆括号,函数的参数传入也能使用{},例如:
scala> println("hello,world")
hello,world
scala> println {"hello,world"}
hello,world
Scala在函数的入参只有一个函数时,允许你使用{}调用函数,不过仅限你的函数只接受一个入参。有了这个铺垫,下面的withFile就容易理解了。withFile是一个柯里化函数,第二个参数列表需要传入一个输入类型为BufferedSource,无返回值的函数,我们借用了{}去模仿Scala的控制结构。一个简单的上下文管理器就实现了。
object withControl{
def main(args: Array[String]): Unit = {
val file = Source.fromFile("D:\\data.txt")
withFile(file) {
writer => println(writer.length)
}
}
def withFile(file: BufferedSource)(op: BufferedSource => Unit) = {
try{
op(file)
}
finally {
file.close()
}
}
}
以上是关于用Scala实现一个简单的Python的上下文管理器的主要内容,如果未能解决你的问题,请参考以下文章