65.9K
CodeProject 正在变化。 阅读更多。
Home

Scala 入门

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2019年7月1日

CPOL

3分钟阅读

viewsIcon

11315

本文通过一个例子解释了关于 Scala 及其功能的几乎所有内容。

Scala 简介

为什么选择 Scala?

Scala 是多范式的,它是面向对象的,函数式的,类型安全的,运行在 Java 虚拟机 (JVM) 上,面向不可变的,这使得用并发和并行(同步)编写代码变得容易。 Scala 是可扩展的,适用于分布式系统。 Scala 代码行优雅而简洁,因为它具有函数式特性,并且仅使用表达式,而没有详细信息,并且有很多定义匿名和嵌套函数的可能性。

有两种主要的编程范式,命令式和声明式。 命令式语言使用一系列语句来完成一个目的,因此代码行比函数式语言多。

什么是函数式编程?

函数式编程是声明式编程的子集,面向对象编程是命令式语言的子集。但是为什么函数式编程会处于技术的最前沿呢? 这是因为它在使用多个处理器或换句话说,在并行编程时具有高效可靠的行为,并且具有最佳性能。

安装 Scala

  1. 根据操作系统下载合适的 JDK (Linux macOS Windows)
    https://www.oracle.com/technetwork/java/javase/downloads/index.html
  2. 设置 Java 环境变量
    Windows

    高级系统设置 -> 环境变量

    Set var JAVA_HOME = C:\{Java Path}\java\jdk{version}
    	Set system var as Path = C:\{Java Path}\java\jdk{version}\bin
    Linux:终端
    Export JAVA_HOME=/usr/local/java{version}
    Export PATH=$PATH:$JAVA_HOME/bin/
  3. 在命令提示符或终端中执行 java –version
  4. 根据操作系统下载合适的 Scala (Linux macOS Windows)

    下载
    与其他编程语言相比,安装 Scala 有些不寻常。 Scala 不寻常,因为它通常...www.scala-lang.org

    选择 IntelliJ 或 SBT 或其他方式安装 Scala,并选择,例如,下载 Windows 的 Scala 二进制文件。 你也可以使用

    https://scalafiddle.io/

    或者你可以使用命令提示符或终端来运行

    java –jar scala{version}-installer.jar
  5. 通过运行 scala –version 进行测试,如果一切正常!

Scala 项目

文件 -> 新建 -> 项目

右键单击解决方案 -> src -> 新建文件

在代码中必须注意的一些重要事实

  1. 对象名称应与此文件名相同,否则,编译会有一些困难。
  2. 折叠所有方法和类的快捷键:Crtl + Shift + -
  3. 展开所有方法和类的快捷键:Crtl + Shift + +

文件 -> 项目结构 -> 库

转到终端并将您的路径设置为您的 Scala 文件

C:\>cd C:\Users\Mahsa\ScalaIntro\src
C:\Users\Mahsa\ScalaIntro\src> scalac ScalaQuickStart.scala
C:\Users\Mahsa\ScalaIntro\src> scala ScalaQuickStart

类 - 对象 - 文件 I/O - 异常处理

import java.io._
import scala.io.Source
import java.io.FileNotFoundException
import java.io.IOException
import Array._

object ScalaQuickStart {
  def main(args: Array[String]) {
    var inc = (x:Int) => x+1
    println(inc(2))
    val rff = new ReadFromFile()
    rff.read()

    val wr = new WriteToFile()
    wr.write()

    var myMatrix = ofDim[Int](2, 2)

    val bufferedSource = Source.fromFile("C:\\file\\grades.csv")
    for (line <- bufferedSource.getLines) {
      println(line)
      val nums = line.split(",")
      println(nums.head, nums.last)
      //bufferedSource.close()
    }
  }

  class ReadFromFile() {
    def read() {
      try {
        Source.fromFile("C:\\file\\grades.csv").foreach {

          print
        }
      }
      catch {
        case ex: FileNotFoundException => {
          println("Missing file exception")
        }

        case ex: IOException => {
          println("IO Exception")
        }
      }
      finally {
        println("finally runs anyway...")
      }
    }
  }

  class WriteToFile() {
    def write() {
      try {
        val writer = new PrintWriter(new File("C:\\file\\grades.txt"))

        writer.write("Hello Scala")
        writer.close()
      }
      catch {
        case ex: FileNotFoundException => {
          println("Missing file exception")
        }

        case ex: IOException => {
          println("IO Exception")
        }
      }
    }
  }

  class ProcessArray() {
    def read() {
      try {
        Source.fromFile("C:\\file\\grades.csv").foreach {

          print
        }
      }
      catch {
        case ex: FileNotFoundException => {
          println("Missing file exception")
        }

        case ex: IOException => {
          println("IO Exception")
        }
      }
      finally {
        println("finally runs anyway...")
      }
    }
  }
}

Collection

函数

函数式编程处于技术最前沿的最重要原因是因为在使用多个处理器或换句话说,在并行编程时具有高效可靠的行为,并且具有最佳性能。

通过尾调用优化避免堆栈溢出

另一个原因是函数式语言中的循环和迭代将通过递归与 TCO(尾调用优化)完成。 TCO 是一种调用函数的方法,不需要单独的堆栈帧工作,并且避免了堆栈溢出。 例如,在下面的代码中,Factorial(4) 计算需要 4 个单独的堆栈帧,而函数式语言中的下一个计算只需要一个堆栈帧。

这不是 TCO

def factorial(n):
        if n == 0:
        return 1
        return n * factorial(n-1)

这是 TCO

def factorial(n):
            return fact(n, 1)
        
        def fact(n, number):
            if n == 0:
            return number
            return fact(n-1, number*n)

通过使用不可变对象作为线程安全来避免竞争条件和死锁

什么是竞争条件?

在多线程概念中,当两个或多个线程试图同时获取共享资源或对象时。

什么是死锁?

在多线程概念中,当进程 1 拥有锁定的资源 2 并等待资源 1 时,恰好在这个时候,进程 2 拥有并锁定资源 1 并等待资源 2。

什么是线程安全?

在多线程概念中,线程安全确保每个线程都可以以同步方式正确执行其执行,而不会出现意外的交互。

什么是不可变的?

不可变对象的状态或值在创建后无法更改。 a 是可变的,因为它的值将被更改

a = 1
b = 2
a = a + b

在创建时,a 应该被定义为只读和不可变的,以防止更改其值。

结论

由于在函数式编程中不可变作为线程安全,因此它对于无限的 forforeach 循环(特别是在数学函数中)很有用,并且可以防止竞争条件和死锁。

历史

  • 2019 年 7 月 1 日:初始版本
© . All rights reserved.