多范式的编程语言--Scala

“为什么要使用Scala?”

Scala的设计始终贯穿着一个理念:创造一种更好地支持组件的语言。(《The Scala Programming Language》,Donna Malayeri)

一、平台和许可证

Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序。它也能运行于Java ME, CLDC(Java Platform, Micro Edition Connected Limited Device Configuration)上。还有另一.NET平台的实现,不过该版本更新有些滞后。

Scala的编译模型(独立编译,动态类加载)与Java和C#一样,所以Scala代码可以调用Java类库(对于.NET实现则可调用.NET类库) 。

Scala包中包含了编译器和类库,以BSD许可证发布。

二、特性

1. 面向对象特性

Scala是一种纯面向对象的语言,每一个值都是对象。对象的数据类型以及行为由类和特征(Trait)描述。类抽象机制的扩展有两种途径。一种途径是子类继承,另一种途径是灵活的混入(Mixin)机制。这两种途径能避免多重继承的种种问题。[4] 

2. 函数式编程

Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化 。Scala的Case Class及其内置的模式匹配相当于函数式编程语言中常用的代数类型(Algebraic Type)。

更进一步,程序员可以利用Scala的模式匹配,编写类似正则表达式的代码处理XML数据。在这些情形中,顺序容器的推导式(comprehension)功能对编写公式化查询非常有用。

由于JVM不支持尾部递归,Scala也不能完全支持尾部递归优化。不过,在简单的情况下,Scala编译器可以把尾部递归优化成循环。

以下代码以函数式风格实现了快速排序算法,可以与Erlang快速排序的例子做个比较:

def qsort(list: List[Int]): List[Int]=

  list match{
    case Nil => Nil
    case pivot::tail =>
      qsort(for(i <- tail if i < pivot)yield i)::: pivot :: qsort(for(i <- tail if i >= pivot)yield i)
  }

3. 静态类型

Scala是具备类型系统,通过编译时的检查,保证代码的安全性和一致性。类型系统具体支持以下特性:

泛型类,型变注释(Variance Annotation),类型继承结构的上限和下限,把类别和抽象类型作为对象成员,复合类型,引用自己时显式指定类型,视图,多态方法。[4] 

4. 扩展性

Scala的设计承认一个事实,即在实践中,某个领域特定的应用程序开发往往需要特定于该领域的语言扩展。Scala提供了许多独特的语言机制,可以以库的形式轻易无缝添加新的语言结构:

任何方法可用作前缀或后缀操作符,可以根据预期类型自动构造闭包。联合使用以上两个特性,使你可以定义新的语句而无须扩展语法也无须使用宏之类的元编程特性。

三、基础语法

关于Scala程序,这是非常要注意以下几点。

1. 区分大小写 -  Scala是大小写敏感的,这意味着标识Hello 和 hello在Scala中会有不同的含义。

类名 - 对于所有的类名的第一个字母要大写。

如果需要使用几个单词来构成一个类的名称,每个单词的第一个字母要大写。

示例:class MyFirstScalaClass

2. 方法名称 - 所有的方法名称的第一个字母用小写。

如果若干单词被用于构成方法的名称,则每个单词的第一个字母应大写。

示例:def myMethodName()

3. 程序文件名 - 程序文件的名称应该与对象名称完全匹配。

保存文件时,应该保存它使用的对象名称(记住Scala是区分大小写),并追加“.scala”为文件扩展名。 (如果文件名和对象名称不匹配,程序将无法编译)。

示例: 假设“HelloWorld”是对象的名称。那么该文件应保存为'HelloWorld.scala“

4. def main(args: Array[String]) - Scala程序从main()方法开始处理,这是每一个Scala程序的强制程序入口部分。

Scala 还提供了一个更简便的方式,直接继承另一个对象 App,无需定义 main方法,编译即可运行。

package com.sunsharing

/**
  * Created by Administrator on 2016/1/24.
  */
object ScalaStudy extends App {
  // 定义函数
  def square(x: Int): Int =
    x * x
  // 如果不是递归函数,函数返回类型可省略
  def sum_of_square(x: Int, y: Int) =
    square(x) + square(y)


  println("平方和", sum_of_square(2, 3))

  // 定义匿名函数
  val cube = (x: Int) => x * x *x
  println("立方", cube(3))

  // 使用匿名函数,返回列表中的正数
  println("正数列表", List(-2, -1, 0, 1, 2, 3).filter(x => x > 0))

  /**
    * if else 求绝对值
    * @param n
    * @return
    */
   def abs(n: Int): Int = if (n > 0) n else -n
  println(abs(-39));

  /**
    * while 求和
    * @param xs
    * @return
    */
   def sum(xs: List[Int]) = {
    var total = 0
    var index = 0
    while (index < xs.size) {
      total += xs(index)
      index += 1
    }
    total
  }
  println(sum(List(3, 4, -5, 54)));

  /**
    * xs.head 返回列表里的头元素,即第一个元素
    * xs.tail 返回除头元素外的剩余元素组成的列表
    * 递归对函数求和
    * @param xs
    * @return
    */
  def recursionSum(xs: List[Int]): Int =
    if (xs.isEmpty) 0 else xs.head + recursionSum(xs.tail)
  println(recursionSum(List(3, 4, -5, 54)));

  println(List(3, 4, -5, 54).foldLeft(0)((x0, x) => x0 + x))


}

5. Scala修饰符:

所有的Scala的组件需要名称。使用对象,类,变量和方法名被称为标识符。关键字不能用作标识符和标识是区分大小写的。Scala支持以下四种类型标识符:

1). 文字标识符

字母数字标识符开始以字母或下划线,可以使用字母,数字或下划线。“$”字符在Scala中是保留关键字,标识符不能使用。以下是合法的字母标识符:

age, salary, _value,  __1_value

以下是非法标识符:

$salary, 123abc, -salary

2). 运算符标识

运算符识别符由一个或多个运算符字符。操作字符是可打印的ASCII字符,如+, :, ?, ~ 或#。以下是合法的运算符标识:

+ ++ ::: <?> :>

Scala编译器将在内部“轧”操作符标识符使它们成为合法的Java标识符,并嵌入$字符。例如,所述标识符:->将内部表示为$colon$minus$greater。

3). 混合标识符

混合标识符由一个字母数字识别符,随后是一个下划线和运算符标识。以下是合法的混合标识符:

unary_+,  myvar_=

在这里,作为一个方法名unary_+定义了一个一元+运算符和myvar_=用来作为方法名称定义了一个赋值运算符。

4). 立即数标识符

一个文字标识是包含在反引号(` . . . `)的任意字符串。以下是合法的文字标识:

`x` `<clinit>` `yield`



6. 空行和空格:

仅包含空格,可能带有注释行,被称为一个空行,并且Scala将会完全忽略它。标记可以通过空格和/或注释分开。

7. 换行符:

Scala是面向行的语言,语句可以用分号(;)结束或换行符。分号在声明的结尾通常是可选的。可以键入一个想要的,如果语句出现其本身在一行。在另一方面,如果写在一行多个语句分号是必需的:

val s = "hello"; println(s)

8. Scala包:

包是一个代码命名的模块。例如,Lift 实用包net.liftweb.util。包声明是在源文件中的第一个非注释行,如下所示:

package com.sunsharing

可以导入封装的类和对象,例如,从scala.collection.mutable导入HashMap:

import scala.collection.mutable

可以从一个单一封装的scala.collection.immutable包导入多个类或对象,例如,TreeMap和TreeSet:

import scala.collection.immutable.{TreeSet, TreeMap}

单行和多行注释非常类似于Java。多行注释可以嵌套,但必须正确嵌套。可用的任何注释和所有字符都将被Scala编译器忽略。

package com.sunsharing

import scala.collection.immutable.{TreeSet, TreeMap}

/**
  * Created by Administrator on 2016/1/23.
  */
object Sort {
  def main(args: Array[String]) {
    //var treeMap = TreeMap(3 -> 'x', 1 -> 'x', 4 -> 'x');
    //var treeSet = TreeSet('f', 'u', 'n')
    var list : List[Int] = List(5, 6, 7, 2, 4);
    println(list)
    list = qsort(list);
    println(list)
  }

  def qsort(list: List[Int]): List[Int]=
    list match{
      case Nil => Nil
      case pivot::tail =>
        qsort(for(i <- tail if i < pivot)yield i)::: pivot :: qsort(for(i <- tail if i >= pivot)yield i)
    }
}


关键词:

多范式的编程语言--Scala_第1张图片

数据类型

多范式的编程语言--Scala_第2张图片


相关链接:

http://www.yiibai.com/scala/scala_basic_syntax.html

http://clayz.iteye.com/blog/1623035


你可能感兴趣的:(多范式的编程语言--Scala)