四,控制结构

scala和其他编程语言有一个根本性差异:在scala中,几乎所有构造出来的语法结构都有值。这个特性使得程序结构更加精简。scala内建的控制结构很少,仅有if、while、for、try、match和函数调用等而已。如此之少的理由是,scala从语法层面上支持函数字面量。

 

if表达式

scala的if/else语法结构与java等一样,但是在scala中if/else表达式有值,这个值就是跟在if/esle后边的表达式的值。如下:

         val s = if(x > 0) 1 else -1

同时注意:scala的每个表达式都有一个类型,比如上述if/esle表达式的类型是Int。如果是混合类型表达式,则表达式的类型是两个分支类型的公共超类型。String和Int的超类型就是Any。如果一个if语句没有else部分,则当if条件不满足时,表达式结果为Unit。如:

                   if(x > 0) 1

就相当于:

                   if(x > 0) 1 else ()

 

while循环

scala拥有与java和c++中一样的while和do-while循环,while、do-while结果类型是Unit。

 

for表达式

scala中没有类似于for(; ;)的for循环,你可以使用如下形式的for循环语句:

         for(i <- 表达式)

该for表达式语法对于数组和所有集合类均有效。具体介绍如下:

枚举:for(i <-1 to 10),其中“i <- 表达式”语法称之为发生器,该语句是让变量i(注意此处循环变量i是val的(但无需你指定),该变量的类型是集合的元素类型)遍历表达式中的所有值。1 to 10产生的Range包含上边界,如果不想包含上边界,可以使用until

过滤:也叫守卫,在for表达式的发生器中使用过滤器可以通过添加if子句实现,如:for(i <- 1 to 10 if i!=5),如果要添加多个过滤器,即多个if子句的话,要用分号隔开,如:for(i <- 1 to 10 if i!=5; if i!=6)。

嵌套枚举:如果使用多个“<-”子句,你就得到了嵌套的“循环”,如:for(i<- 1 to 5; j <- 1 to i)。

流间变量绑定:你可以在for发生器以及过滤器等中使用变量保存计算结果,以便在循环体中使用,从而避免多次计算以得到该结果。流间变量绑定和普通变量定义相似,它被当作val,但是无需声明val关键字。

制造新集合:for(…) yield变量/循环体,最终将产生一个集合对象,集合对象的类型与它第一个发生器的类型是兼容的。

         实际上:for表达式具有等价于组合应用map、flatMap、filter和foreach这几种高阶函数的表达能力。实际上,所有的能够yield(产生)结果的for表达式都会被编译器转译为高阶方法map、flatMap及filter的组合调用;所有的不带yield的for循环都会被转译为仅对高阶函数filter和foreach的调用。正是由于这几个高阶函数支持了for表达式,所以如果一个数据类型要支持for表达式,它就要定义这几个高阶函数。有些时候,你可以使用for表达式代替map、flatMap、filter和foreach的显式组合应用,或许这样会更清晰明了呢。

 

scala中没有break和continue语句。如果需要类似的功能时,我们可以:

         1)使用Boolean类型的控制变量

         2)使用嵌套函数,你可以从函数当中return

         3)...

 

match表达式模式匹配

scala中没有switch,但有更强大的match。它们的主要区别在于:

①  任何类型的常量/变量,都可以作为比较用的样本;

②  在每个case语句最后,不需要break,break是隐含的;

③  更重要的是match表达式也有值;

④  如果没有匹配的模式,则MatchError异常会被抛出。

match表达式的形式为:选择器 match{ 备选项 }。一个模式匹配包含了一系列备选项,每个都开始于关键字case。每个备选项都包含了一个模式以及一到多个表达式,它们将在模式匹配过程中被计算。箭头符号“=>”隔开了模式和表达式。按照代码先后顺序,一旦一个模式被匹配,则执行“=>”后边的表达式((这些)表达式的值就作为match表达式的值),后续case语句不再执行。示例如下:

                   a match {

                            case1 => "match 1"

                            case_ => "match _"

                   }

match模式的种类如下:

①  通配模式:可以匹配任意对象,一般作为默认情况,放在备选项最后,如:

case _ =>

②  变量模式:类似于通配符,可以匹配任意对象,不同的是匹配的对象会被绑定在变量上,之后就可以使用这个变量操作对象。所谓变量就是在模式中临时生成的变量,不是外部变量,外部变量在模式匹配时被当作常量使用,见常量模式。注意:同一个模式变量只能在模式中出现一次。

③  常量模式:仅匹配自身,任何字面量都可以作为常量,外部变量在模式匹配时也被当作常量使用,如:

case "false" =>"false"

case true=> "truth"

case Nil=> "empty list"

对于一个符号名,是变量还是常量呢?scala使用了一个简单的文字规则对此加以区分:用小写字母开始的简单名被当作是模式变量,所有其他的引用被认为是常量。如果常量是小写命名的外部变量,那么它就得特殊处理一下了:如果它是对象的字段,则可以加上“this.”或“obj.”前缀;或者更通用的是使用字面量标识符解决问题,也即用反引号“`”包围之。

④  抽取器模式:抽取器机制基于可以从对象中抽取值的unapplyunapplySeq方法,其中,unapply用于抽取固定数量的东东,unapplySeq用于抽取可变数量的东东,它们都被称为抽取方法,抽取器正是通过隐式调用抽取方法抽取出对应东东的。抽取器中也可以包含可选的apply方法,它也被称作注入方法,注入方法使你的对象可以当作构造器来用,而抽取方法使你的对象可以当作模式来用,对象本身被称作抽取器,与是否具有apply方法无关。样本类会自动生成伴生对象并添加一定的句法以作为抽取器,实际上,你也可以自己定义一个任意其他名字的单例对象作为抽取器使用,以这样的方式定义的抽取器对象与样本类类型是无关联的。你可以对数组、列表、元组进行模式匹配,这正是基于抽取器模式的。

⑤  类型模式:你可以把类型模式当作类型测试和类型转换的简易替代,示例如下:

case s: String => s.length

⑥  变量绑定:除了独立的变量模式之外,你还可以把任何其他模式绑定到变量。只要简单地写上变量名、一个@符号,以及这个模式。

模式守卫:模式守卫接在模式之后,开始于if,相当于一个判断语句。守卫可以是任意的引用模式中变量的布尔表达式。如果存在模式守卫,只有在守卫返回true的时候匹配才算成功。

         Option类型:scala为可选值定义了一个名为Option的标准类型,一个Option实例的值要么是Some类型的实例,要么是None对象。分离可选值最通常的办法是通过模式匹配,如下:

                   case Some(s) => s

                   case None => “?”

         模式无处不在:在scala中,模式可以出现在很多地方,而不单单在match表达式里。比如:

①  模式使用在变量定义中,如下:

val myTuple = (123, “abc”)

val (number, string) = myTuple

②  模式匹配花括号中的样本序列(即备选项)可以用在能够出现函数字面量的任何地方,实质上,样本序列就是更普遍的函数字面量,函数字面量只有一个入口点和参数列表,样本序列可以有多个入口点,每个都有自己的参数列表,每个样本都是函数的一个入口点,参数被模式所特化。如下:

val withDefault: Option[Int] => String = {

         case Some(x) => "is int"

         case None => "?"

}

③  for表达式里也可以使用模式。示例如下:

for((number, string) <- myTuple) println(number +string)

         模式匹配中的中缀标注:带有两个参数的方法可以作为中缀操作符使用,使用中缀操作符时实际上是其中一个操作数在调用操作符对应的方法,而另一个操作数作为方法的参数。但对于模式来说规则有些不同:如果被当作模式,那么类似于p op q这样的中缀标注等价于op(p,q),也就是说中缀标注符op被用做抽取器模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值