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

条件表达式:

Scala的if else语法结构和Java的一样,不过,Scala的if else表达式有值,这个值就是跟在if或者else后面的表达式的值。

例如: if(x>0) 0 else 1

该表达式的值就是0或者1,具体的根据x值判断。

可以将if else表达式的值赋值给变量:

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

这个跟如下语句一致:

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

当然,第一种写法更好,它可以用来初始化一个val(常量),而第二种s必须是var(变量)。

  注:Scala中的分号(;)绝大多数情况下不是必需的。

        Java中的 x>0 ? 0:1 等同于 Scala表达式if(x>0) 0 else 1

Scala中,每个表达式都有一个类型。表达式if(x>0) 0 else 1的类型是Int,因为两个分支的类型都是Int。

混合类型表达式if(x>0) "hello" else 1,这个表达式的类型是两个分支类型的公共超类型,示例中,“hello”是java.lang.String类型,1是Int类型,

其公共超类型为Any。

如果else部分没有,if(x>0) 0 ,有可能if没有输出值。但在Scala中,每个表达式都是有值的。该示例中,如果if没有输出值,那么其输出就是一个“无有用值”占位符,

写作(),其类是Unit类,类似Java中的Void。上述语句等同于if(x>0) 0  else () 。

注: 在Scala中没有Switch语句,其存在强大的模式匹配机制(后面会讲到)。

       语句终止:

            在Java中,每个语句都有分号,而在Scala中,行尾的位置不需要分号。在}、else及类似的位置也不必写分号,只需要能够从上下文判断这里是语句终止即可。

如果需要在单行写下多个语句,就需要分号将这些语句隔开。如:

if(x>0) { k = r*x ; n +=4}  通过分号将k = r*x  与n +=4 这个语句隔开,由于存在} ,所有n +=4结尾不需要加分号;

如果书写过长的语句,需要分开两行来写的话,确保第一行以一个不能用做语句结尾的符号结尾。比较好的选择是用操作法结尾。

如:  sum = s0 + (V1-V2)*t +   //  告诉解析器这里不是语句的结尾

0.8*(V3-V4)*t+s1

在实际编码中,通过使用Kemighan&Ritchie风格的花括号编码。如:

if(x>0) {

n = n*x

x -=1

}

以{结尾告诉编译器后面还存在内容。

       块表达式和赋值:

              Java中,块语句是一个包含于{}中的语句序列。但逻辑分支或者循环中放置多个语句是,都可以使用块语句。

Scala中,{}块语句包含一系列的表达式,其结果也是一个表达式。块的最后一个表达式的值就是块的值。

这个特性对某个val初始化需要分多个步骤完成的情况很有用。如:

val dis = { val x = t1-t2; val y = t3 -t4 ; sum(x,y)}

{}块中取值最后一个表达式,即sum(x,y)。变量x,y对程序的其它部分不可见。

Scala中赋值动作本身没有值,更准确的说,他们的值是Unit类型的,类似Java中的void,写作();

一个以赋值语句结尾的块,如:{r -=2;n= r+1} 的值是Unit类型的。

语句: x = y =1 //别这么做

y=1的值是(),故x的值是(),相信你的本意不是这样。

   输入和输出:

          如果需要打印,用print或者println函数,后者打印完成后会追加一个换行符。

print ("hello")

println("world")

等价于 println("hello"+"world"),这个类似Java中的System.out.println("hello"+"world");

    循环:

  Scala拥有与Java一样的while和do循环。如:

while(n>0) {

r = r*n

n -=1

}

         scala没有同java中for(初始化变量;检查变量是否满足条件;更新变量 )对应的循环结构。在Scala中你有两个选择:

1:使用while循环;

2:使用如下for语句;

for(i <- 1 to n)

r = r *i

这个是RichInt类的to方法, 1 to n 这个调用返回数字1到数字n的区间。

for(i <- 表达式)让变量i遍历<-右边的表达式中的所有值。遍历如何执行,取决于表达式的类型。

在for循环的变量之前并没有声明变量为val或者var,该变量的类型是集合的元素类型。循环变量的作用域一直持续到循环结束。

遍历字符串或者数组时,通常使用0到n-1的区间。在Scala中可以用util方法而不是to方法。util方法返回一个并不包含上限的区间。

val s = "hello"

var sum = 0

for(i <- 0 to util s.length)

sum += s(i)

这里i的最后一个取值为s.length-1

            注:Scala中没有提供break和continue语句退出循环。

   Scala退出循环的方式:

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

2.使用嵌套函数--可以从函数中return

3.使用Breaks对象的break方法:

    高级for循环和for推导式:    

                        1:使用变量<-表达式形式提供多个生成器,分号分割

                               

        

2:每个生成器可以带一个守卫,以if开头的Boolean表达式:(if之前没有分号)

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

分析:i == 1 时,from=3; j从3 到3 故输出13

i==2 时,from=2;j从2到3,循环两次,故输出22,23

i== 3 时,from=1;j从1到3,循环3此,故输出31 32 33

4:for循环的循环体内已yield开始,则给循环会构造出一个集合,每次迭代生成集合中的一个值,这类循环称为推导式。

其类型是Vector。

for推导式生成器的集合与它的第一个生成器的类型是兼容的。

第一个for循环 ,第一个类型是 String ;

第二个for循环,第一个类型是Int;

Scala基础之函数:

    Scala除了方法,还支持函数。方法对对象进行操作,函数不是。

     定义函数,需要给出函数的名称、参数和函数体。如:

      def sum(x:int) = if(x>=0) x else -x

      函数需要给出所有参数的类型。只要函数不递归,就不需要知道返回列下。Scala可以根据=号右侧表达式推导出放回类型。

      如果函数体需要多个表达式完成,可以使用代码块。块的最后一个表达式的值就是函数的返回值。如:

        

[java] view
plain
copy

  1. def sum(n:Int) = {
  2. for (i <- 1 to 10)
  3. r = r*i
  4. r
  5. }

         此函数r即是函数的返回值。如果使用return返回r的值,那么需要明确指定函数返回类型,如下所示:

         

[java] view
plain
copy

  1. def sum(n:Int):Int = {
  2. for (i <- 1 to 10)
  3. r = r*i
  4. return r
  5. }

          其与上面的是一样的,只是上面的写法更简洁。

     如果是递归函数,同样需要指定返回类型。如:

   

[java] view
plain
copy

  1. def fac(n:Int):Int = if( n <= 0) 1 else n*fac(n-1)
  2. println(fac(5)) //120

默认参数和代码参数:

     

有些情况下我们不需要给出全部参数,对应这类函数我们可以使用默认参数,当然你需要知道参数顺序或者参数名称。如:

         

[java] view
plain
copy

  1. def outputBookName(bookname:String,left:String="{",right:String="}") =
  2. left + bookname + right
  3. println(outputBookName("book1"))
  4. println(outputBookName("book2", "[", "]"))
  5. println(outputBookName(right="***]",bookname="book3"))

输出:

       {book1}   --》使用了默认参数

[book2]    --》 使用了传入的参数

{book3***] --》根据需要,提供参数名称和值替换默认值

变长参数:

      实现一个可以接受可变长度的参数列表的函数,如:

    

[java] view
plain
copy

  1. def sum1(args : Int*) = {
  2. var result = 0
  3. for(arg <- args)
  4. result += arg
  5. result
  6. }
  7. println(sum1(5,4,3,2,1)) //15

   实现一个序列作为参数传入上述函数中,需要追加 _*,告诉编译器希望把这个参数当做序列处理。如:

 

[java] view
plain
copy

  1. val s = sum1(1 to 5: _*)  //将1到5当做参数序列处理

 在递归中我们同样可以使用这种方式,如:

 

[java] view
plain
copy

  1. def sum2(args : Int*):Int = {
  2. if(args.length == 0 )
  3. 0
  4. else
  5. args.head + sum2(args.tail: _*)
  6. }

序列的head是参数args的首个元素,而tail是所有其它的元素序列,这是个Seq,需要用 _*将它转为参数序列。

过程:

   定义:

    Scala对不返回值的函数有特殊的表示法。如果函数体包含在花括号中但没有前面的=号,那么返回类型是Unit。这样的函数叫做过程。

过程不返回值,我们调用它是为了使用它的副作用。如:我们需要打印一些图案,那么可以定义一个过程:

 

[java] view
plain
copy

  1. def draw(s:String) {
  2. println("-------")
  3. println("|"+"   "+"|")
  4. println("|"+s+"|")
  5. println("|"+"   "+"|")
  6. println("-------")
  7. }
  8. println(draw("123"));
  9. 输出:
  10. -------
  11. |   |
  12. |123|
  13. |   |
  14. -------
  15. ()

看上面的返回,可以明显的指定这个函数的返回值是Unit;

懒值:

     当val被声明为lazy时,它的初始化将被推迟,知道我们首次取它的值。如:

    

[java] view
plain
copy

  1. lazy val file1 = scala.io.Source.fromFile("C:/hello.scala").mkString
  2. println(file1)

输出:

println("hello")

如果我们不调用

[java] view
plain
copy

  1. println(file1)

  这行语句,即file1不被访问,那么文件就不会被打开。

    

异常:

 Scala异常的工作机制同Java。当你需要抛出异常时,如:

   throw new FileNotFoundException("系统找不到指定的文件。")

Scala异常同Java一样,抛出的异常必须是java.lang.Throwable的子类。其与Java不同的是,Scala没有受检异常,不需要声明函数或者方法可能会抛出异常。

throw 表达式有特殊类型Nothing。这在if else表达式中很有用。如果一个分支的类型是Nothing,那么if else表达式的类型就是另外一个分支的类型。

捕获异常的语法采用模式匹配的语法。如:

try finally语句可以释放资源,不论是否发生异常。如:

[java] view
plain
copy

  1. var in = new URL("http://ubmcmm.baidustatic.com/media/v1/0f0000g0bymVB3uhUffi-0.gif").openStream();
  2. try {
  3. process(in)
  4. }finally {
  5. in.close()
  6. }
  7. def process(in:java.io.InputStream) = {
  8. println(in.toString());
  9. }

输出:[email protected]e8

以上借鉴http://blog.csdn.net/wangmuming/article/details/35226275

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

时间: 2024-12-20 13:21:27

Scala详解---------控制结构和函数的相关文章

Scala学习(二)--- 控制结构和函数

控制结构和函数 摘要: 本篇主要学习在Scala中使用条件表达式.循环和函数,你会看到Scala和其他编程语言之间一个根本性的差异.在Java或C++中,我们把表达式(比如3+4)和语句(比如if语句)看做两样不同的东西.表达式有值,而语句执行动作.在Scala中,几乎所有构造出来的语法结构都有值.这个特性使得程序更加精简,也更易读.本篇的要点包括: 1. 表达式有值 2. 块也有值,是它最后一个表达式的值 3. Scala的for循环就像是"增强版"的Java for循环 4. 分号

标准文件IO详解(九)---fileno函数详解

在前面笔记“打开流详解”中提到了 fdopen 函数,可以通过文件描述符 fd 来获取对应的文件流指针.而同时 C 库函数提供了 fileno 函数,这个函数的作用就是能够通过 文件流指针来获取对应的 文件描述符 fd . ======================================================= 函数原型: 函数参数: stream:要操作的文件流指针 返回值: 函数返回与文件流指针对应的文件描述符,此函数不会出错(和umask函数类似) =========

文件IO详解(五)---open函数详解

open函数用来在进程中打开文件,如果成功则返回一个文件描述符fd. ======================================================= 函数原型: 函数参数: pathname:打开文件的路径名 flags:用来控制打开文件的模式 mode:用来设置创建文件的权限(rwx).当flags中带有O_CREAT时才有效. 返回值: 调用成功时返回一个文件描述符fd 调用失败时返回-1,并修改errno ==========================

文件IO详解(七)---lseek函数详解

lseek函数用来设置当前文件偏移量. ====================================================== 函数原型: 函数参数: fd:要操作的文件描述符 offset:基于whence参数的偏移量 whence:参考点位置 返回值: 调用成功时返回当前相对于文件开头的偏移量,以字节为单位 调用失败时返回 -1,并修改errno的值 ======================================================= when

Scala详解---------数组相关操作

Scala中提供了一种数据结构-数组,其中存储相同类型的元素的固定大小的连续集合.数组用于存储数据的集合,但它往往是更加有用认为数组作为相同类型的变量的集合. 取替声明单个变量,如number0, number1, ..., 和number99,声明一个数组变量,如号码和使用numbers[0],numbers[1],...,numbers[99]表示单个变量.本教程介绍了如何声明数组变量,创建数组和使用索引的过程变量数组.数组的第一个元素的索引是数字0和最后一个元素的索引为元素的总数减去1.

php调用C代码的方法详解和zend_parse_parameters函数详解

http://blog.csdn.net/super_ufo/article/details/3863731 php调用C代码的方法详解 在php程序中需要用到C代码,应该是下面两种情况: 1 已有C代码,在php程序中想直接用 2 由于php的性能问题,需要用C来实现部分功能 针对第一种情况,最合适的方法是用system调用,把现有C代码写成一个独立的程序.参数通过命令行或者标准输入传入,结果从标准输出读出.其次,稍麻烦一点的方法是C代码写成一个daemon,php程序用socket来和它进行

【Oracle】详解Oracle常用函数

Oracle SQL 提供了用于执行特定操作的专用函数.这些函数大大增强了 SQL 语言的功能.函数可以接受零个或者多个输入参数,并返回一个输出结果. Oracle 数据库中主要使用两种类型的函数: 1.  单行函数:对每一个函数应用在表的记录中时,只能输入一行结果,返回一个结果, 比如:MOD(x,y)返回 x 除以 y 的余数(x 和 y 可以是两个整数,也可以是表中的整 数列).常用的单行函数有: Ø  字符函数:对字符串操作. Ø  数字函数:对数字进行计算,返回一个数字. Ø  转换函

Scala详解--------基础知识详解

Chapter1 1.Scala解释器 启动Scala解释器的方法如下: 自己总结的: 1.打开执行命令栏WIN+R  ,输入cmd,在命令行上输入Scala等待启动如下 如上面所示即可启动Scala 2.使用bin内部的启动脚本 找到你所安装Scala的目录,并在Scala的bin文件夹中找到scala.bat文件,打开即可. 以上是我知道的打开方式,另外,可以使用eclipseEE进行安装插件,进行使用,具体的使用情况可以参考上一篇文章. 下面来测试一下Scala编译器的效果吧 测试成功,说

Scala详解---------快速入门Scala

我无可救药地成为了Scala的超级粉丝.在我使用Scala开发项目以及编写框架后,它就仿佛凝聚成为一个巨大的黑洞,吸引力使我不得不飞向它,以至于开始背离Java.固然Java 8为Java阵营增添了一丝亮色,却是望眼欲穿,千呼万唤始出来.而Scala程序员,却早就在享受lambda.高阶函数.trait.隐式转换等带来的福利了. Java像是一头史前巨兽,它在OO的方向上几乎走到了极致,硬将它拉入FP阵营,确乎有些强人所难了.而Scala则不,因为它的诞生就是OO与FP的混血儿--完美的基因融合