Scala学习手册--可伸缩的语言(随着使用者的需求而成长) java
第一章:基本概念 程序员
Scala=FP+OO、静态语言 编程
兼容性、简短、高层级抽象、高级的静态类别、伸缩性 api
兼容:与Java兼容,可无缝实施互操做。Scala程序会被编译为JVM的字节码。性能一般一致。Scala能够调用Java方法,访问Java字段,继承自Java类和实现Java接口。实际上,几乎全部的Scala代码都极度依赖于Java库。 数组
交互式操做的另外一面是:Scala极度重用了Java类型,Int-->int,Float-->float,Boolean-->boolean。Scala的数组被映射到Java数组。Scala一样重用了许多标准Java库类型。 数据结构
Scala不只重用,并且增长了更多特性或改进,Scala字符串支持相似于toInt,toFloat的方法。 并发
隐式转换:这一般在类型失配,或许选用不存在的方法时。在上面的例子里,当在字串中寻找toInt方 异步
法时,Scala 编译器会发现String 类里没有这种方法,但它会发现一个把Java的String ide
转换为Scala 的RichString类的一个实例的隐式转换,里面定义了这么个方法。因而在 函数式编程
执行toIn t 操做以前,转换被隐式应用。
Scala 代码一样能够由Java代码调用。有时这种状况要更加微妙,由于Scala 是一种比Java
更丰富的语言,有些Scala 更先进的特性在它们能映射到Java 前须要先被编码一下。
简洁:分号可不写,且一般不写;类与构造函数的简写;类型推断
class MyClass(index: Int , name: String) //写得少就不多犯错误 |
高层级:业务逻辑的复杂带来了复杂的代码,过分复杂又带来了系统性能或致使崩溃。这种复杂无可避免,因此就须要由不受控转为受控。
Scala经过使用接口的抽象级别来帮助你管理复杂性。
函数式文本:
val nameHasUpperCase = name.exists(_.isUpperCase) //判断String 包含一个大写字符 |
Scala是静态类型的:这就容许它提供泛型类、内部类、甚至多态方法(Polymorphic Method)。另外值得一提的是,Scala被特地设计成可以与Java和.NET互操做。
语法轻量级,原语富有表达力,这些能够从拆分器、组合器和执行器中体现
scala被普遍使用:渗透性、可伸缩性
var capital = Map ("US"->"Washington", "France" -> "Paris") capital += ("Japan" -> "Tokyo") println(capital("France" )) |
本例中的声明都是高层次的,也就是说,没有被外加的分号或者类型注释弄得乱糟糟的。实际上,这种感受就好像那种现代的“脚本化”语言,好比,Perl ,Python或者Ruby。这些语言的一个广泛特征,与上例有关的,就是它们都在语法层面上支持“关联映射”。
方便性和灵活性
关联映射很是有用,由于它能让程序易读和清晰。
Scala更像一个杂货铺而不是大教堂,由于它被设计为让用它编程的人扩展和修改的。
新的类型
许多程序须要一个可以变得任意大都不会溢出或者因为数学操做而“绕回”
的整数类型。Scala在库类Scala.BigInt中定义了这样一个类型。这里有一个使用了那个
类型的方法定义,用以计算传入整数的阶乘值:
def factorial(x: BigInt): BigInt = if (x == 0) 1 else x * factorial(x - 1) 调用:factorial(30) 结果:265252859812191058636308480000000 |
BigInt 看上去就像一个内建的类型,由于你可使用整数值和这种类型值的操做符如* 和- 。然而它只是凑巧定义在Scala标准库中的类。6若是这个类缺失了,能够直接由任意的Scala程序员写一个实现出来,举例来讲,经过包装Java的类java.math.BigInteger(实际上,
Scala的BigInt 就是这么实现的)。
调用Java API实现:
import java.math.BigInteger def factorial(x:BigInteger): BigInteger = if (x == BigInteger.ZERO) BigInteger.ONE else x.multiply(factorial(x.subtract(BigInteger.ONE)))
|
新的共享/并发程序
Java的线程模型是围绕着共享内存和锁创建的,尤为是当系统在大小和复杂度都获得提高的时候,这种模型经常是不可理喻的。
Java伴随着一个丰富的,基于线程的并发库。Scala 能够像其余JavaAPI 那样使用它编程。
然而,Scala 也提供了一个实质上实现了Erlang的行动类模型的附加库。
行动类是可以实现于线程之上的并发抽象。它们经过在彼此间发送消息实现通讯。每一个行
动类都能实现两个基本操做,消息的发送和接受。发送操做,用一个惊叹号表示,发送消
息给一个行动类。这里用一个命名为recipient 的行动类举例以下:
recipient ! msg
发送是异步的;就是说,发送的行动类能够在一瞬间完成,而不须要等待消息被接受和处
理。每个行动类都有一个信箱:mailbox 把进入的消息排成队列。行动类经过receive
代码块处理信箱中受到的消息:
receive { case Msg1 => ... // handle Msg1 case Msg2 => ... // handle Msg2 // ... } |
接收代码块由许多case 语句组成,每个都用一个消息模板查询信箱。信箱中第一个符
合任何case的消息被选中,而且执行相应的动做。若是信箱中不含有任何符合任何case的消息,行动类将休眠等待新进的消息。
这里举一个简单的Scala 行动类实现检查值(cheksum)计算器服务的例子:
actor { var sum = 0 loop { receive { case Data(bytes) => sum += hash(bytes) case GetSum(requester) => requester ! sum } } } |
这个行动类首先定义了一个名为sum 的本地变量,并赋了初值为零。而后就用receive段
落重复等待在消息循环中。若是收到了Data 消息,就把发送的bytes取哈希值加到sum
变量中。若是收到了GetSum 消息,就用消息发送requester!sum 把当前sum 值发回给
requester。requester 字段嵌入在GetSum 消息里;它一般指出建立请求的行动类。
实际上,对于可伸展性这个话题来讲这个例
子里面最重要的是,不管是actor仍是loop 仍是receive仍是发送消息的符号“!”,这
些都不是Scala 内建的操做符。尽管actor,loop 和receive 看上去或者表现上都如此接
近于控制结构如while或者for 循环,实际上它们是定义在Scala 的行动类库里面的方法。
一样,尽管“!”看上去像是个内建的操做符,它也不过是定义在行动类库里面的方法。
全部这四个构件都是彻底独立于Scala 语言的。
Scala 具备伸缩性
Scala 在把面向对象和函数式编程熔合成一套语言的设计方面比其余众所周知的语言都走
得更远。比方说,其余语言或许把对象和方法做为两个不一样的概念,但在Scala 里,函数
值就是对象。函数类型是可以被子类继承的类。这看上去彷佛不外乎学术上的美感,但它
从深层次上影响了可伸展性。实际上以前看到的行动类这个概念若是没有这种函数和对象
的联合将没法实现。
Scala函数式编程的主要思想:
第一理念:函数是第一类值,能够把函数看成参数传递给其余函数,看成结果从函数中返回或保存在变量里。你也能够在函数里定义其余函数,就好像在函数里定义整数同样。还能够定义匿名函数。
把函数做为第一类值为操做符上的抽象和建立新控制结构提供了便利的方法。这种函数的
泛化提供了很强的表现力,常能产生很是易读和清晰的程序。并且常在伸展性上扮演重要
的角色。例如,以前在行动类例子里演示的receive构造就是一个把函数看成参数调用的
方法。receive构造里面的代码是个未被执行的传入receive方法的函数。
相反,在多数传统语言中,函数不是值。确实有函数值的语言则又经常把它们贬为二类地
位。举例来讲,C 和C++ 的函数指针就不能拥有与非函数指针在语言中同等的地位:函数
指针仅能指向全局函数,它们不容许你定义指向环境中什么值的第一类嵌套函数,也不能
定义匿名函数文本。
第二理念:程序的操做符应该把输入值映射到输出值而不是就地修改数据。
在Java和Scala 里,字串是一种数学意义上的字符序列。
使用表达式如s.replace(';', '.')在字串里替换字符会产生一个新的,不一样于原字串s
的对象。用另外一种表达方式来讲就是在 Java里字串是不可变的(immutable)而在 Ruby
里是可变的。所以单看字串来讲,Java是函数式语言,而 Ruby 不是。不可变数据结构是
函数式语言的一块基石。Scala 库在Java API 之上定义了更多的不可变数据类型。例如,
Scala 有不可变的列表,元组,映射表和集。
第三理念:方法不该有任何反作用:side effect。它们惟一的与所在环境交流的方式应该是得到参数和返回结果。
举例来讲,Java 的String 类的replace 方法符合这个描述。它带一个字串和两个字符并产生一个全部一个字符都被另外一个替代掉的新字串。调用replace不会有其余的结果。相似于 replace这样的方法被称为指称透明:referentially transparent ,就是说方法调用对任何给定的输入能够用它的结果替代而不会影响程序的语义。
函数式语言鼓励不可变数据结构和指称透明的方法。有些函数式语言甚至须要它们。Scala给你选择。若是你须要,你也能够写成命令:imperative 形式,用可变数据和有反作用的方法调用编程。可是Scala 一般能够在你须要的时候轻松避免它们,由于有好的函数式编程方式作替代。
第二章、语法学习
1.变量:声明变量可使用val和var,val相似于java里的final变量,一旦初始化就不可变;var如同java里的非final变量,能够在其生命周期内屡次赋值。
类型推导:type inference,理解你省略的类型的能力。
函数及返回值缩写规则:
1:能够不写返回值,由编译器自动推导 2:若是函数方法体能够用一个句子组成,能够省略{} 如:scala> def max2(x: Int , y: Int ) = if (x > y) x else y 3:函数不带参数也没有返回值,好比:
greet表示函数名,()表示参数特色--不带参数,Unit是greet的结果类型(在Java里被认为是返回值),Unit表示函数没有返回有用户的值(实际上scala里的Unit会被编译器映射为Java里的void)。
|
循环:
while循环
var i = 0 while (i < args.length) { println(args(i)) i += 1 //scala只支持i+=1或者i=i+1,不支持i++/++i自增操做 }
var r=0; var i=1; while(i<100){r+=i*i;i+=2}; |
foreach和for枚举