码迷,mamicode.com
首页 > 其他好文 > 详细

Scala详解-----------控制结构和函数

时间:2015-07-22 22:57:43      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:

Scala学习——控制结构和函数

本章的一开始,是两个容易混淆的概念——表达式(expression)和语句(statement)。表达式有值,而语句没有值只执行操作。

要说起这一点的原因是,Scala中,几乎所有构造出来的语法结构都有值,也就是表达式。这可以使程序更加精简易读。

举例,if表达式是有值的;语句块也是有值的,是最后一个表达式的值。

而对应Java中的void,Scala中有一个类型Unit,用来表示“无有用值”(void表示没有值,这里还是有差别的)。

条件表达式

if/else表达式在Scala中是有值的,除开这一点,与Java等语言没有什么差别。而有值所带来的效果,可以是下面这样子的:

第一种写法可以用来初始化一个val,而第二种则要求s必须是var。前面也说了,Scala中更鼓励使用val。

同时,这样的条件表达式,还可以实现比三目操作符 ? : 更加灵活的功能。

如果在if和else两边的类型是不同的,比如:

这时返回的类型将会是两个分支类型的公共超类型(这里是String和Int的公共超类型Any)。

如果没有else部分,那么if表达式有可能不返回值,这时候就需要前面提到的Unit类型,写做()。

 语句终止

分号不是必须的,但是使用它们不会带来坏处。

能根据上下文判断出语句结尾的地方,都不需要使用分号。怎么判断是否语句结尾,以后在编码过程中会慢慢积累起感觉的。

如果需要在单行中写多个语句,那么就需要使用分号了。而在写一个较长的语句时,如果需要分行写,要确保前面的行尾需要以不能用来语句结尾的符号来结束。比如说像是下面的操作符:

这里还可以发现的是,Scala推荐使用两个空格来缩进。

由于判断语句终止的需要,Scala程序员更倾向于使用Kernighan & Ritchie风格的花括号(也就是Java中推荐的方法):

 块表达式和赋值

Scala中,{ }包含一系列的表达式,而且{ }最后返回的也是一个表达式——最后一个表达式。

而赋值语句的值,是Unit类型的。这也大体上决定了在Java和C++中的 x = y = 1 会出现的赋值语句,几乎不可能出现在Scala中。

输入和输出

输入函数: readLine()、 readInt()等,用来从控制台Console中读取输入。

而输出部分,则是很常见的 print()、 println()、 printf()

循环

对于一个纯粹的Java程序员来说,这里会发现一些平时没有接触到的东西。而我在这之前算是稍稍碰了下Python,所以还是能比较好地接受,虽然说一开始的时候真的难以理解。这里也可以知道,Java对我的束缚有多大了,门槛低,好学易用,但真的过于死板了。

Scala中有与Java类似的while循环和do循环,但却没有最常使用的 for ( ; ; )这种形式的循环(但还是有for循环的)。

同时,Scala中也没有break和continue语句来控制循环。替代的解决方案就是使用变量和条件语句来进行循环的控制。要使用break时,可以有集中选项:

1. 使用Boolean型的控制变量;

2. 使用嵌套函数,可从函数中return;

3. 使用Breaks对象中的break方法,这种方法中,控制权转移是通过异常来完成的,所以在追求时间上的效率时,要尽量避免使用。

看看Scala中的for循环:

事实上,Scala中更多是使用函数式而不是指令式的风格来遍历等操作。后面会见到的。

高级for循环和for推导式

在一个for循环中使用多个“generator”(生成器):

在for循环中使用“filter ”(过滤器,守卫)来过滤一部分不符合条件的枚举情况:

可以使用多个filter,中间需要使用分号分隔。

可以在for表达式中使用任意多的定义,引入在循环中使用变量:

如果for表达式的循环体是以yield关键词开始的,那么该循环会构造出一个集合,这被称为for推导式。推导式生成的集合与第一个generator是类型兼容的。

想当初学Python的时候,完全搞不懂这yield到底是做什么的…现在算是理解了,接触的东西多了之后,理解能力和推广能力真是有明显提升的。

还可以将for表达式的小括号换成花括号,这样可以省去写分号的功夫。

for表达式内容不少,而且这里也不是全部。在《Programming in Scala》中,还有一些高级的讨论,这里就先略了,先入个门。

函数

在Java中并没有函数这个概念,函数的功能是用静态方法来实现的。

函数的定义:

只要函数不是递归的,就不需要给出函数的返回值类型(因为有类型推断)。一个递归的函数需要如下写:

在Scala中,并不时常使用return来返回值。

默认参数和带名参数(技能层级L1)

Java里似乎没有默认参数和带名参数,至少我从来没有使用过。但记得C++是有的。

上面的函数有两个带有默认值的参数left和right。如果不给出这两个参数,调用这个函数,会使用默认值。也可以给出自己的参数来替代默认的。

参数个数不够时,将会从后往前使用默认参数。

调用函数时,如果指定参数名,那么参数可以不按照参数列表的顺序来:

从上面还可以知道,可以混用未命名参数和带名参数。

变长参数(L1)

觉得写详细了太慢了,还是简要提一提给自己记个笔记就好了…

星号表示可接受变长参数列表。函数实际得到的参数是Seq类型的。

但是在调用变长参数函数时,并不能直接使用Seq类型的参数。要将一个Seq类型打散成单个的参数序列,使用 : _*

 过程(procedure)

又来了一个过程…过程是不返回值的函数。

过程的定义与函数很类似。函数体在花括号中,而且花括号前没有=号,返回值是Unit类型的,这就是过程了。(也可以写出=号,并且写明返回值是Unit类型来定义过程。)

通常,过程没有返回值,只是为了副作用而调用一个过程。

懒值(L1)

当val被声明为lazy时,初始化会被推迟到首次对其取值时。

如果程序一直不妨问words,那么Scala也不会去打开那个文件。文件是在实际第一次使用words时被打开的。

懒值对开销较大的初始化语句十分有用,可以应对一些初始化问题比如循环依赖。还是开发懒数据结构的基础。

可以将懒值当成是介于val和def的中间状态:

  • val在被定义时即被取值
  • lazy val在首次使用时被取值
  • def在每次使用时取值

异常

Scala中异常机制与Java和C++中一样。但Scala中并没有受检异常,也就是不需要说明函数方法可能会抛出什么异常。

使用throw来抛出一个异常。throw表达式的类型是Nothing。

捕获异常:

如果不需要使用捕获的异常对象,使用_来代替变量名(_是Scala中的通配符)。

同时也有try/finally语句,通常用来清理。可以组合成try/catch/finally语句,但书上说这种写法几乎没什么用。(这是为什么为什么,我在Java中都这么写啊….)


本章的习题解答参考。网上还能找到几个不同的方案。

4.  for (i <- 0 to 10 reverse) println(i)

6.

7. 这个实现方法真的好多,不过考虑到现学的东西还不多,先用简单的吧。

9.

版权声明:欢迎转载,希望在你转载的同时,添加原文地址,谢谢配合

Scala详解-----------控制结构和函数

标签:

原文地址:http://blog.csdn.net/u011225629/article/details/47009815

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!