scala语言的一些体会

这两天用scala写了一些程序,有一些体会。

 

scala作为一种函数式语言,特别适合将多个小的匿名函数串联起来,作用到一个列表对象(Option/Either/List/Map等)上。并且这么做会减少一些想临时变量名字的功夫,诱惑人不断把这种串联持续下去。比如:

 

val match = Option(fileName).map(new File(_)).map(Path(_).slurpString).map {str =>
  val s = "^" + str + "$"
  s.r.pattern
}.map.(_.matcher("hello world").matches).get

 

这种代码看起来很简短,但写起来和读起来其实都很费力,因为连续的小函数之间,都是隐藏起来的数据在流转。这些数据是什么类型,必须根据小函数的返回值来确定。而任何一个小函数的输入,都需要从前一个小函数的返回值获得。这样要看懂一句话的涵义,就必须从头开始,中间不能有任何中断,否则就无法知道下一步是怎么做的。

 

这种做法对于比较简短的一些操作非常有用,类似在shell中使用管道将几个非常熟练的命令行命令串联起来,看起来一目了然,非常清晰。但在编程语言中,由于过多的小括号甚至大括号,换行和断句,要看懂一句话是非常困难的。

 

当然,上述命令可以使用中缀表达式省去一些"."和小括号,看起来好看一些:

 

  val match1 = Option(str) map (new File(_)) map (Path(_).slurpString) map {
      str => ("^" + str + "$").r.pattern
    } map {p => p matcher("hello world")}.matches.get 

 

但这仍然不够。shell中,无论何时,我们知道管道间的输入输出,实际上只有一种类型的数据:字节流,所以我们无需费心想这个命令的输出和那个命令的输入分别是什么类型的,最后实际上我们都几乎忘了某个命令的输出类型,直接就使用其字面语义就直接明白命令串的涵义了。但scala中不同。首先列表都有好几种类型:Option,Either,List,Map,虽然每种的操作名字都是类似的,但就是因为这种类似性,在看一句语句的过程中,经常忘了这个到底是什么列表类型,需要到头上去看一下。

 

更可悲的是,有时候在脑海中相处某个匿名函数的返回值也比较困难。最可悲的是,经常遇到某些函数有几行,此时用大括号括起来,并且换行处理,就会变得比较痛苦。

 

所以,这种串联的确非常有意义,不过要变得有用,必须简短,一个原则就是:一行搞定,然后赋值给一个变量。如果有多行,就多加几个中间变量。这样做的好处很明显:人的思维深度是有限的,在某个地方就应该停一下,把中间思考结果记下来,然后继续思考。上面的代码应该可以这样写:

 

val rstr = Option(str) map {new File(_)} map {Path(_).slurpString}

val pattern = rstr map {str => ("^" + str + "$").r.pattern}

val result = pattern map {p => (p matcher "hello world").matches} get

 

看着清爽了不少。可以与java代码比较一下:

 

File file = new File(str);
String content = (new Path(file)).slurpString();
Pattern p = ("^" + str + "$").r().pattern();
boolean result = p.matcher("hello world").matches();
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值