关闭

Scala语法要点

541人阅读 评论(0) 收藏 举报

Scala语法要点

比较有用的链接收集如下。
官方的语法要点:http://docs.scala-lang.org/cheatsheets/
不错的教程:http://www.tutorialspoint.com/scala/
还可以但不太清楚:http://www.code123.cc/672.html

变量和函数的声明

Scala中比较奇怪的是变量和函数声明,譬如:

// 下面是两种变量,一种是普通变量,另外一种类似C++的引用
var v0 = 10
val v1 = 10
// 函数的声明,用的def关键字,但是也用等号
def f0(): Unit = {
  println("this is a function")
}

Scala的函数返回值Unit是没有返回值的意思,参数也是类似UML格式,但是更重要的是和变量声明一样,用=来指名后面是函数体。

延迟求值

函数的参数可以延迟求值,譬如参数传进去是函数变量时,或者类型是函数变量时。
对于函数参数是变量的延迟求值,譬如:

// 延迟求值,参数可以是函数变量
def max(a: Int, b: Int): Int = {
    if (a < b) return b else return a
}
println(t0(max(10, 11)))
// 下面的例子中,max会在t0中求值,而不是求值后把结果作为参数传进去,
// 也就是延迟求值,即call-by-name
def t0(v: => Int): Int = {
    return v * 3;
}
// 下面的例子中,max会求值后再传给t0,即call-by-value
def t0(v: Int): Int = {
    return v* 3
}

对于函数参数是函数变量时,即明确定义参数的函数原型时,譬如:

// 延迟求值,参数可以是函数变量,注意传参方式变了,三个参数了。
def max(a: Int, b: Int): Int = {
    if (a < b) return b else return a
}
println(t0(max, 10, 11))
// 因为第一个参数是函数,所以必须要延迟求值,也就是必须call-by-name
// 注意使用参数v的方式也变了。
def t0(v: (Int, Int) => Int, a: Int, b: Int): Int = {
    return v(a, b) * 3
}

函数参数

函数的参数只有一种形式,即def f(v: Type): Type = {},也就是说,所有的参数都是v: Type,即名称和类型。
但是有几种不同的情况,譬如:

  1. v: Int,这种就是普通参数,call-by-value,预先求值的。
  2. v: => Int,这种就是普通参数,call-by-value,延迟求值的。可以把=> Int看做是类型,这种类型就说明是延迟求值。
  3. v: (Int) => Int,这种就是参数类型是函数,必须是call-by-value。这个时候函数的返回值肯定就是参数的值,那么它们的类型也就是一样了。可以认为原本是v: (Int): Int => Int(注意这样是有语法问题的),其中(Int): Int就是函数的类型,两个参数一样就省略返回值,简写成v: (Int) => Int

匿名函数

匿名函数是声明函数时没有指定函数名称,譬如传递给函数时作为参数,或者赋值给变量时。
声明匿名函数的方式和函数是不一样的,不用def,不用=定义,不包含返回值,而是用=>指定body。也就是匿名函数的声明语法是特定的,不同于函数,譬如:

(x: Int) => {
  // function body, param is x
}

匿名函数作为函数参数,譬如:

  def t0(v: (Int, Int) => Int, a: Int, b: Int): Int = {
    return v(a, b)
  }
  def anonyFunc(): Int = {
    t0((a: Int, b: Int) => {
      println("anonymous function, a=" + a + ", b=" + b)
      return a+b
    }, 10, 11)
  }

或者作为函数变量的用法:

  def anonyFunc2(): Unit = {
    val f = (a: Int, b: Int) => {
      println("anonymous function as variable, a+b=" + (a+b))
      return a+b
    }
    f(10, 11)
  }

因此,closure和high order function等都很好理解了。

总结

综合上面的语法原则,各种组合就很明确了。
譬如有个帖子讨论下面两个函数定义的差别:

// http://scalagroup.group.iteye.com/group/topic/26303
def test(code: => Unit){ code } 
def test1(code: () => Unit){ code }

分析这个代码,test和test1都是两个函数,区别在于参数不一样。

  1. code: => Unit,类似于code: Unit即没有类型,但是=> Unit表明这个是call-by-name的,即延迟赋值。
  2. code: () => Unit,这个参数类型是函数():Unit,返回值和参数类型一样是Unit,也就是这个函数参数为空返回值为空。另外,因为是函数参数所以必须是call-by-name的。

再看另外一个教程的例子:

// http://www.tutorialspoint.com/scala/scala_closures.htm
val multiplier = (i:Int) => i * 10

分析这个代码,这个是个变量定义,右边是个匿名函数,也就是它是这么写的:

val multiplier = (i: Int) => {
    return i * 10
}

这个就比较清楚了,multipler就是个函数变量,一个整型参数,返回值推导出来也是个整型的。所以使用时应该multiplier(10)结果是100

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:555947次
    • 积分:7869
    • 等级:
    • 排名:第2637名
    • 原创:239篇
    • 转载:11篇
    • 译文:10篇
    • 评论:263条
    文章分类
    最新评论