Scala学习杂谈
Posted 小熊的技术之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala学习杂谈相关的知识,希望对你有一定的参考价值。
项目中需要使用Scala+Play Framework,之前一直使用命令式和面向对象的语言为主,这次接触Scala顺带学习了函数式的编程思想,感受颇深,这篇文章主要是一些学习心得。Scala使用了快半年,我的感触是它和C++一样,给予了程序员非常大的自由,它的主要设计思想应该在Scalable, 即可扩展性。作为一个诞生于2004年(正式发布)的晚辈语言,它充分吸取了Java, C++乃至C#的一些思想,个人认为是一门很有特色的语言。
学习Scala我主要按顺序看了下面的资料:
twitter的scala课程;
书:scala for the impatient;
书:Programming in Scala;
Why Scala
作为同样运行在JVM之上的语言,Scala在设计的时候就吸取了很多Java的经验和教训,下面是我感触最深的几个:
string comparsion
no checked exception
这个见仁见智,但是在书<Programming in Scala>中提到,Java中增加checked exception是为了让程序员处理和考虑程序中可能抛出的异常,但是大部分程序员为了编译通过直接try...catch掉所有异常,导致程序运行时出现问题无法通过异常来处理。这其实是设计思想的哲学,Scala不愿意去限制程序员而是去帮助他们,Java这个feature的设计其实是强制程序员去遵守规则,反而引起了新的问题。这个有点像政府的政策实施,本意是好的,结果却造成了更大的问题。
mutli-thread support using Futures/AKKA
Java中使用多线程,比较方便的方法只有Execute框架,但是依然不够方便,因为其中的Future.get是阻塞式的,想要写出非阻塞的代码只能自己再创建一个线程去get,然后通过共享变量去传递,这个不仅容易出bug,也非常不好维护,所以本质上Java的多线程开发是基于锁机制的。
Scala本身FP的编程方式就是对并行友好的,例如val设置不可变变量,而Future则是一种非常方便的多线程开发框架。Future本身代表了一段需要异步执行的代码,而这个线程的创建,管理和注销由框架负责,也就是说程序员只需要写异步的代码即可,具体异步的执行不用理会,这使得编写全异步的代码变得非常简单,著名的基于Scala的Web框架Play Framework就是一个大量使用Future的异步模型,这使得部署了Play的机器单机就可以处理大量的请求,而不用把时间和资源浪费在I/O上,详见这篇文章。
除此之外,Scala还有另一个非常著名的AKKA框架提供基于Actor模型的并发编程,所以Scala是一门对异步非常友好的语言。
Why Scala is Scalable?
我之前在开头提到过,Scala的设计哲学之一就是Scalable。这个在各种语法特性的设计上都有体现。
operators are methods, methods can also be used like operators
操作符即函数,相比于Java不允许对操作符进行重载,Scala则要灵活的多,不但是我可以自由定义操作符,连本身的内置的操作符本质上也是函数,通过操作符我们可以实现很多看起来像内置操作符的特性,例如AKKA里面的消息发送原语。
control abstraction
控制抽象,因为有了高阶函数等特性的存在,我们可以把控制抽象出来当作参数传递,这样可以有效的减少代码重复,提高代码可读性。
而Scala更进一步,开发者可以自由扩展出很多控制结构,就像Scala内置的while, for等一样,最后这一点充分说明了其扩展性的强大之处。这里面主要使用的语法特性是currying以及by-name parameter.
我们要自定义任何一个控制结构只需要实现一个函数,这个函数接受一个高阶函数作为参数,同时使用by-name parameter可以在高阶函数是空参数时,调用时不用写括号。详见下面的例子:
这个时候twice是不是看起来很像一个内置的控制结构?这种特性对于写库很实用。
combinator parsing
这个特性我在刚看到的时候也有点小惊讶,Scala居然提供了内置的Domain Language实现一个简单的解析器!这样我们实现简单的内置语言就十分方便了,我们只要定义好语法结构和范式,直接按照语法生成规则写即可。
traits and implict convertion together make rich wrapper for certrain classes
我在使用Scala的过程中发现,其实Scala用的是Java的String,但是却有比Java的String更加丰富的操作,这是怎么实现的?为了一探究竟,我首先定义了下面的测试代码:
接着我使用scalac的-Xprint:typer选项来查查是否有隐式转换,一看果然有:
我们看到,str这个变量在调用count方法时,编译器发现没有在String内找到这个方法,所以使用了Predef里的隐式转换augmentString。而这个的定义在翻看Predef的代码可以看到:
这个String其实被转换成了StringOps类型,但是StringOps里并没有count函数,我发现这个类mix了StringLike这种trait, 并一级一级mix了 TraversableOnce, 而count就在这里定义了。通过trait可以非常方便的丰富任意瘦接口,使得扩展方法变得非常方便,而隐式转换则使得调用方在无感知的情况下就可以调用。
How to learn Scala?
可以说,Scala就是为扩展而生的,理解Scala的关键就是扩展,这也是很多Scala语法的设计思想,也正是因为此,Scala的缺点也很明显,学习曲线很陡峭,从新手,到能看懂一般人写的代码,到最终自己写代码,以至于写出scala native的代码,需要花费大量的时间,这里基于我自己走过的路,对于即将和刚学习Scala不久的同学给点建议吧:
永远按照自己的学习需求来做投入,如果只是需要看懂别人写的代码,则不必花太多时间,毕竟Scala的学习曲线是很陡峭的,建议看看孟岩老师写的这篇文章:《快速掌握一个语言最常用的50%》;
新手阶段,结合twitter的scala课程和scala for the impatient就足够了,可以对基本语法做个详细了解;
想要更加细致的了解,需要看看Scala作者的这本书Programming in Scala;
Scala有很大一块是函数式编程,这块语法糖实在太多,需要了解under the hood,就要开始吭红宝石书《Functional Programming in Scala》;
学习下Scala周边的东西,例如AKKA;
再学有余力,可以啃Scala的Specification了;
当然学习任何语言都有一个铁律,那就是不断的练习,而且是刻意练习。
以上是关于Scala学习杂谈的主要内容,如果未能解决你的问题,请参考以下文章