快学Scala-第二章 控制结构和函数

知识点:

1.条件表达式 if(x>0) 1 else 0

scala每个表达式都有一个类型,如果一致则为它们的类型,如果为混合类型表达式,则为它们的公共超类型Any。
if(x>0) 1 可能没有输出值,在scala中,每个表达式都应该有某种值,引入Unit类,写作()。

if(x>0) 1 等同于 if(x>0) 1 else ()

2. 语句终止,如果在写较长的语句,需要分两行来写的话,就要确保第一行以一个不能用作语句结尾的符号结尾,通常用操作符。

3.块表达式和赋值,块中最后一个表达式的值就是块的值,赋值语句的值是Unit类型,因此不能串接一起。

4.打印:print\println,用readLine函数从控制台读取一行输入,用readInt、readByte、readDouble、readShort、readLong、readFloat、readBoolean、readChar读取不同数值字符。

5.循环

for(i <- 表达式) 让变量i遍历<- 右边表达式的所有值

to方法:1 to n 返回数字1到n(含)的Range区间,until方法返回一个并不包含上限的区间。

for(i <- 0 until “scala”.length) 等同于 for(i <- “scala”)

可以以 变量<- 表达式 的形式提供多个生成器,用分号隔开,每个生成器都可以带一个守卫。

for(i <- 1 to 3 ; j <- 1 to 3 if i != j) print((10 * i +j) +” ”) //将打印 12 13 21 23 31 32

for推导式:如果for循环的循环体以 yield 开始,则该循环会构造出一个集合,每次迭代生成集合中的一个值。for推导式生成的集合与它的第一个生成器是类型兼容的。

for(i <- 1 to 10) yield i % 3 //生成 Vector(1,2,0,1,2,0,1,2,0,1)

6.方法对对象进行操作,函数不是。Scala的函数也包括 名称、参数和函数体。必须给出所有参数的类型,只要函数不是递归的(编译器无法校验递归函数的返回类型)就不需要指定返回类型,函数体中最后一个表达式的值就是函数返回值。

7.函数的默认参数和带名参数,相对参数的数量,给出的值不够,默认参数会从后往前逐个应用进来,带名参数并不需要跟参数列表的顺序完全一致,如果混用未命名参数和带名参数,只要那些未命名的参数是排在前面的即可。

8.变长参数

def sum(args:Int*)={ var result = 0; for(arg <- args) result += arg; result}

val s = sum(1,2,3,4,6)

函数得到的是一个类型为Seq的参数,用for循环访问每一个元素。但如果已经有一个值得序列,则不能直接传入函数中,需要告诉编译器希望这个参数被当做参数序列处理,追加:_*.

val s = sum(1 to 5:_*)

9.过程:如果函数体包含在花括号当中但没有前面的=号,那么返回类型就是Unit,这样的函数成为过程,过程不返回值。

10.当val被声明为lazy时,它的初始化将被推迟,直到首次对它取值。懒值对于开销较大的初始化语句有用,是介于val和def的中间状态,val在被定义时即被取值;lazy在被首次使用时取值;def在每一次被使用时取值。

11.异常Scala没有“受捡”异常,不需要声明说函数或方法可能会抛出某种异常。控制器将在离抛出点最近的处理器中恢复,如果没有找到符合要求的异常处理器,则程序退出。throw表达式有特殊的类型Nothing,在if/else表达式中很有用,如果一个分支的类型是Nothing,那么if/else的类型就是另一个分支的类型。

 



练习:(参考CSDN上下载的资料)

1.一个数字如果为正数,则它的signum为1;如果是负数,则signum为-1;如果为0,则signum为0.编写一个函数来计算这个值。

scala> def signum(num:Int)={
     | var r=0
     | if(num>0) r=1
     | else if(num<0) r= -1
     | else r=0
     | r}
signum: (num: Int)Int

scala> print(signum(5))
1
scala> print(signum(0))
0
scala> print(signum(-8))
-1

一定要注意函数的返回值有个等号,不然就是返回Unit。r= –1,等号和负号要隔开,不然报错“value =- is not a member of Int”。

Scala中已经有此方法了。

scala> BigInt(5).signum
res6: Int = 1

2.一个空的块表达式{}的值是什么?类型是什么?

scala> print({})
()
scala> def test={}
test: Unit
scala> var kong = {}
kong: Unit = ()

类型是Unit,值为()。

3.指出在Scala中何种情况下赋值语句x=y=1是合法的。(提示:给x找个合适的类型定义)

书本中说赋值语句的类型是Unit,所以给x定义类型Unit即合法了。

scala> var x={}
x: Unit = ()

scala> var y=1
y: Int = 1

scala> x=y=0
x: Unit = ()

4.针对下列Java循环编写一个Scala版本:

      for(int i=10;i>=0;i–)System.out.println(i);

scala> for(i <- 0 to 10 reverse) print(i+"\n")

5.编写一个过程countdown(n:Int),打印从n到0的数字。

scala> def countdown(n:Int){
     | for(i <- 0 to n reverse)
     | print(i+" ")
     | }
countdown: (n: Int)Unit

scala> countdown(5)
5 4 3 2 1 0

6.编写一个for循环,计算字符串中所有字母的Unicode代码的乘积。举例来说,"Hello"中所有字符串的乘积为9415087488L。

scala> var l:Long = 1
l: Long = 1

scala> for(i <- "Hello"){
     | l=l*i.toLong
     | }

scala> l
res14: Long = 9415087488

7.同样是解决前一个练习的问题,但这次不使用循环。(提示:在Scaladoc中查看StringOps)

scala> var t:Long = 1
t: Long = 1

scala> "scala".foreach(t *= _.toLong)

scala> t
res18: Long = 11569118220

8.编写一个函数product(s:String),计算前面练习中提到的乘积。

scala> def product(s:String):Long={
     | var t:Long = 1
     | for(i <- s){
     | t *= i.toLong
     | }
     | t
     | }
product: (s: String)Long

scala> print(product("scala"))
11569118220

9.把前一个练习中的函数改成递归函数

scala> def product(s:String):Long={
     | if(s.length == 1) return s.charAt(0).toLong
     | else s.take(1).charAt(0).toLong * product(s.drop(1))
     | }
product: (s: String)Long

scala> print(product("scala"))
11569118220

10.编写函数计算xn,其中n是整数,使用如下的递归定义:

xn=y2,如果n是正偶数的话,这里的y=x(n/2)

xn = x*x(n-1),如果n是正奇数的话

x0 = 1

xn = 1/x(-n),如果n是负数的话

不得使用return语句。

scala> def mten(x:Double,n:Int):Double={
     | if(n==0) 1
     | else if(n>0 && n%2==0) mten(x,n/2) * mten(x,n/2)
     | else if(n>0 && n%2==1) x * mten(x,n-1)
     | else 1/mten(x,-n)
     | }
mten: (x: Double, n: Int)Double

scala> print(mten(2,3))
8.0
scala> print(mten(2,-3))
0.125
时间: 2024-10-26 04:52:04

快学Scala-第二章 控制结构和函数的相关文章

快学Scala习题解答—第二章 控制结构和函数

2 控制结构和函数 2.1 一个数字如果为正数,则它的signum为1;如果是负数,则signum为-1;如果为0,则signum为0.编写一个函数来计算这个值 简单的逻辑判断 Scala代码   def signum(num:Int){if(num>0)print(1)else if(num<0)print(-1)else print(0)} Scala中已经有此方法了,刚才查找API的时候,应该能看到 Scala代码   BigInt(10).signum 2.2 一个空的块表达式{}的值

快学Scala 第二课 (apply, if表达式,循环,函数的带名参数,可变长参数,异常)

apply方法是Scala中十分常见的方法,你可以把这种用法当做是()操作符的重载形式. 像以上这样伴生对象的apply方法是Scala中构建对象的常用手法,不再需要使用new. if 条件表达式的值就是跟在if或else之后的表达式的值,如果两者类型不同,选择各分支类型的公共超类型作为返回类型. if(x>1) 1 相当于 if(x>1) 1 else () 你可以把()当做是表示"无有用值"的占位符,将Unit当做Java的Void 如果你在写较长的语句,需要分行来写的

快学Scala 第二十一课 (初始化trait的抽象字段)

初始化trait的抽象字段: trait Logged { println("Logged constructor") def log(msg: String){ println("Logged")} } trait FileLogger extends Logged { var filename: String override def log(msg: String) { println("filename:" + filename) } }

快学Scala 第二十二课 (apply和unapply)

apply和unapply: apply方法经常用在伴生对象中,用来构造对象而不用显式地使用new. unapply是当做是伴生对象的apply方法的反向操作.apply方法接受构造参数,然后将他们变成对象.而unapply方法接受一个对象,然后从中提取值.unapply方法返回的是一个Option. object ScalaRunner { def main(args: Array[String]): Unit = { testApply2() testApplyUnApply() testC

快学scala笔记.

第一章 基础 val 定义的值实际上是一个常量 var 声明其值可变的变量 val xmax,ymax = 100 var greeting,message: String = null 1.3 常用类型 Scala的7种数值类型:Byte.Char.Short.Int.Long.Float和Double 1.toString() 2.to(10) "Hello".intersect("World") 1.4 算术和操作符重载 val answer = 8 * 5

快学Scala习题解答—第一章 基础

1 简介 近期对Scala比较感兴趣,买了本<快学Scala>,感觉不错.比<Programming Scala:Tackle Multi-Core Complexity on the Java Virtual Machine>好很多. 是本不错的入门书.而且每个章节都设置了难度级别,每章有习题,可以巩固Scala语法. 本文的目的就是针对这些习题进行解答 2 基础 2.1 在Scala REPL中键入3,然后按Tab键.有哪些方法可以被应用? 这个....直接操作一遍就有结果了.

快学scala 第十一章 操作符 读书笔记及习题答案代码

chapter 11 操作符 标签:快学scala 一.笔记 scala种可以在反引号中包含几乎任何字符序列, val 'val' = 42 所有的操作符都是左结合的,除了以冒号(:)结尾的操作符,和赋值操作符.用于构造列表的::操作符是又结合的.1::2::Ni1的意思是1::(2::Ni1),先创建出包含2的列表,这个列表又被作为尾巴拼接到以1作为头部的列表中. 2. 函数调用语法:f(arg1, arg2,...)扩展到可以应用于函数之外的值,如果f不是函数或方法,那么这个表达式等于f.a

快学Scala课后习题答案

分享一个之前做快学Scala的课后习题(2-21章节,19无)的Github链接,我把习题的文字写在了每个回答的注释上面,这样方便大家对照着看,省的回过头去对照着pdf看了,如果有做的不对的地方希望大家给予指正. 链接如下,http://github.com/fxxkinglife/scala-hello. 举一个第二章节的例子, object charpter02 { /* * 2.1 * 一个数字如果为正数,则它的signum为1; * 如果是负数,则signum为-1; * 如果为0,则s

快学Scala 第十九课 (trait的abstract override使用)

trait的abstract override使用: 当我看到abstract override介绍的时候也是一脸懵逼,因为快学scala,只介绍了因为TimestampLogger中调用的super.log依旧是个abstract class,所以必须在方法前加上abstract和override.但是并没有具体介绍如何使用,然后查阅了其他文档,才明白使用方法. 下面的代码定义了超类LoggerEmpty,这个定义意味着该特质只能混入扩展LoggerEmpty的类中. 在特质中声明抽象方法中有