浅谈Scala语法基础

 

     编程语言设计中提到,一门语言包含了语法,语义,语用几个部分;语法是对语言规则的描述,语义是对语法单位,单词符号意义的定义;而了解语言的语法规则,语言特性,社区支持,生态发展是入门一门语言的基本过程。

    接下来我先从常见一些基本语法来一起探索Scala

1.变量:

1)常量:又称不变量,表示变量定义后值不能再更改,scala语言中推崇使用不变量,用val关键字表示

  val aa = 1 或 val aa: Int = 1

2) 变量:用var关键字表示 


var bb = 1 或 var bb: Int = 1

bb = 2

3) lazy 值:

val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString  // 定义的时候取值

lazy  val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString  //在words首次使用的时候取值,以后一直是这个值

def words = scala.io.Source.fromFile("/usr/share/dict/words").mkString      //在每一次words使用的时候取值

 初始化特征:懒值初始化的时候并没有取值,只有当你首次去调用他的时候他才执行;一般用于如下场景:

  •   解决开销较大的语句
  •   应对其他初始化问题如:循环依赖
  •   开发懒数据结构的基础如:流(stream)

 这点感兴趣的同学可以看看haskell的惰性求值

2.操作符:

操作符包括基本的运算操作符(+,-,/,*)和位操作符(&,|,^,>>,<<)操作方式与Java中类似,但是在Scala中原则中“一切都是对象”例:

val c = a - 1 等同于 val c = a.-(1) 假设a为一个Int对象,-实际是Int对象的方法

 

3.特殊方法:

1)apply方法

BigInt(123456)实际上等同于 BigInt.apply(123456)

 apply在scala中是构建对象常用的方法如: Array(1,2,3,4,5)

2) unapply方法

    case class ScalaUnapply(a: Int, b: String)

    ScalaUnapply(1, "3") match {
      case ScalaUnapply(a, b) => println(a)
      case _ => println("match failure!!!")
    }

ScalaUnapply类是个case类,默认提供unapply方法,所以实际执行match的流程是:

  • ScalaUnapply类先调用自己的unapply方法并返回Option[(Int, String)];
  • case 匹配后发现是个Option类会将其解开,并判断个数,然后将1赋值个a变量,"3"赋值给b变量;

类似的方法还有unapplySeq

4.控制结构

1)表达式与语句的区别:

  • 表达式的目的是计算出一个值,而语句的目的是产生一个side effect。
  • 表达式有值,而语句没有值只执行操作 
  • 表达式是可以被求值的代码,而语句是一段可执行代码;因为表达式可被求值,所以它可写在赋值语句等号的右侧,而语句不一定有值,所以像import、for和break等语句就不能被用于赋值。

在Scala中,几乎所有构造出来的语法结构都有值,也就是表达式。这可以使程序更加精简易读。
 例:if表达式是有值的;语句块也是有值的,是最后一个表达式的值而对应Java中的void,Scala中有一个类型Unit,用来表示“无有用值”(void表示没有值,这里还是有差别的)    
 

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

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

// 与上等效的另一种写法

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

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

if (x > 0) "positive" else -1

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

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

if (x > 0) 1

// 这相当于else部分返回Unit类型,相当于下面的写法

if (x > 0) 1 else ()

 

2)循环控制    
for结构
Scala中有与Java类似的while循环和do循环,但却没有最常使用的 for ( ; ; )这种形式的循环(但还是有for循环的)。同时,Scala中也没有break和continue语句来控制循环。替代的解决方案就是使用变量和条件语句来进行循环的控制。要使用break时,可以有集中选项:

  • 使用Boolean型的控制变量;
  • 使用嵌套函数,可从函数中return;
  • 使用Breaks对象中的break方法,这种方法中,控制权转移是通过异常来完成的,所以在追求时间上的效率时,要尽量避免使用。
import scala.util.control.Breaks._
breakable{
      for (i <- 1 to 9){
        if (i == 5) {
          break
        }
      }
    }

while结构

    var i = 10
    do {
      i = i - 1  
    } while (i>0)
while (true){

    }


高级for和for的推导式
在一个for循环中使用多个“generator”(生成器):

for (i <- 1 to 3; j <- 1 to 3) print ((10 * i +j) + " "

// 结果:11 12 13 21 22 23 31 32 33

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

for (i <- 1 to 3; j <- 1 to 3 if i != j) print ((10 * i + j) + " ")

// 结果:12 13 21 23 31 32

可以使用多个filter,中间需要使用分号分隔。可以在for表达式中使用任意多的定义,引入在循环中使用变量:

for (i <- 1 to 3; from = 4 - i; j <- from to 3) print ((10 * i + j) + " ")

// 结果:13 22 23 31 32 33

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

for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar

// 生成"HIeflmlmop"

for yield结构的应用远不止于此,后面会单独谈到他

 

3)块表达式:

Scala中,{ }包含一系列的表达式,而且{ }最后返回的也是一个表达式——最后一个表达式。而赋值语句的值,是Unit类型的。这也大体上决定了在Java和C++中的 x = y =1 会出现的赋值语句,几乎不可能出现在Scala中。


4)语句终止:
分号不是必须的,但是使用它们不会带来坏处。能根据上下文判断出语句结尾的地方,都不需要使用分号。怎么判断是否语句结尾,以后在编码过程中会慢慢积累起感觉的。如果需要在单行中写多个语句,那么就需要使用分号了。而在写一个较长的语句时,如果需要分行写,要确保前面的行尾需要以不能用来语句结尾的符号来结束。比如说像是下面的操作符:

a = s0 + (v - v0) * t + // +说明了这里不是语句结束哦

  0.5 + (a - a0) * t * t

// 下面这种写法就会出问题了

a = s0 + (v - v0) * t

  + 0.5 + (a - a0) * t * t

这里还可以发现的是,Scala推荐使用两个空格来缩进。由于判断语句终止的需要,Scala程序员更倾向于使用Kernighan & Ritchie风格的花括号(也就是Java中推荐的方法):

if (n > 0) {

  r = r * n

  n -= 1

}


5.函数与过程:
函数:

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

def 函数名(指明类型的参数): 可选的返回值类型 = 函数体

def fac(n: Int) = {

  var r = 1

  for (i <- 1 to n) r = r * i

  r

}


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

def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n - 1)


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

过程:
过程是不返回值的函数。过程的定义与函数很类似。函数体在花括号中,而且花括号前没有=号,返回值是Unit类型的,这就是过程了。(也可以写出=号,并且写明返回值是Unit类型来定义过程。)通常,过程没有返回值,只是为了副作用而调用一个过程.


6.异常处理

scala中没有“受检异常”的概念,scala的设计者认为“受检异常”并不是最好的如:

 public static void main(String[] args) throws IOException {
   // 指在编译器对异常进行检测,如果你的方法要抛出异常,就必须声明异常
 }

过早的捕获异常或者采用通用的异常并不是最好的;

throw 表达式有特殊的类型Nothing来标识

  val res: Int = {
      if (x == 0) {
        1
      }
      else throw Exception
    }
异常捕获结构
try{

}
catch{
  case e: Exception =>
  case _ =>
}
finally{
}


 

 

转载于:https://my.oschina.net/wii01/blog/891132

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值