Scala runs on...

  • JVM
  • JavaScript in your browser
  • Natively with LLVM beta

Scala in a Nutshell

单击下面的框,查看运行中的Scala!

Seamless Java Interop

Scala在JVM上运行,因此Java和Scala堆栈可以自由混合以实现完全无缝的集成.

Type Inference

因此,类型系统不会感到那么静止. 不要为类型系统工作. 让文字系统为您服务!

Concurrency & Distribution

在集合上使用数据并行操作,在并行和分配上使用参与者,在异步编程中使用期货.

Author.scala
class Author(val firstName: String,
    val lastName: String) extends Comparable[Author] {

  override def compareTo(that: Author) = {
    val lastNameComp = this.lastName compareTo that.lastName
    if (lastNameComp != 0) lastNameComp
    else this.firstName compareTo that.firstName
  }
}

object Author {
  def loadAuthorsFromFile(file: java.io.File): List[Author] = ???
}
App.java
import static scala.collection.JavaConversions.asJavaCollection;

public class App {
    public List<Author> loadAuthorsFromFile(File file) {
        return new ArrayList<Author>(asJavaCollection(
            Author.loadAuthorsFromFile(file)));
    }

    public void sortAuthors(List<Author> authors) {
        Collections.sort(authors);
    }

    public void displaySortedAuthors(File file) {
        List<Author> authors = loadAuthorsFromFile(file);
        sortAuthors(authors);
        for (Author author : authors) {
            System.out.println(
                author.lastName() + ", " + author.firstName());
        }
    }
}

Combine Scala and Java seamlessly

Scala类最终是JVM类. 您可以创建Java对象,调用它们的方法并从Scala透明地继承自Java类. 同样,Java代码可以引用Scala类和对象.


在此示例中,Scala类Author实现Java接口Comparable<T>并与Java File . Java代码使用来自伴随对象Author的方法,并访问Author类的字段. 它还使用JavaConversions在Scala集合和Java集合之间进行转换.

类型推断
scala> class Person(val name: String, val age: Int) {
     |   override def toString = s"$name ($age)"
     | }
defined class Person

scala> def underagePeopleNames(persons: List[Person]) = {
     |   for (person <- persons; if person.age < 18)
     |     yield person.name
     | }
underagePeopleNames: (persons: List[Person])List[String]

scala> def createRandomPeople() = {
     |   val names = List("Alice", "Bob", "Carol",
     |       "Dave", "Eve", "Frank")
     |   for (name <- names) yield {
     |     val age = (Random.nextGaussian()*8 + 20).toInt
     |     new Person(name, age)
     |   }
     | }
createRandomPeople: ()List[Person]

scala> val people = createRandomPeople()
people: List[Person] = List(Alice (16), Bob (16), Carol (19), Dave (18), Eve (26), Frank (11))

scala> underagePeopleNames(people)
res1: List[String] = List(Alice, Bob, Frank)

Let the compiler figure out the types for you

Scala编译器对静态类型很聪明. 大多数时候,您不需要告诉它变量的类型. 相反,其强大的类型推断功能将为您解决它们.

在此交互式REPL会话(Read-Eval-Print-Loop)中,我们定义一个类和两个函数. 您会发现编译器会自动推断函数的结果类型以及所有中间值.

Concurrent/Distributed
val x = Future { someExpensiveComputation() }
val y = Future { someOtherExpensiveComputation() }
val z = for (a <- x; b <- y) yield a*b
for (c <- z) println("Result: " + c)
println("Meanwhile, the main thread goes on!")

Go Concurrent or Distributed with Futures & Promises

在Scala中,可以使用Future和Promise 处理数据,从而更轻松地并行化甚至分发应用程序.

在此示例中, Future{}构造异步计算其参数,并将异步结果的句柄作为Future[Int] . 将来完成时(即计算完成时),可以使用理解来注册新的回调(发布新的操作). 由于所有这些操作都是异步执行的,没有阻塞,因此主程序线程可以在此期间继续进行其他工作.

Traits

将Java风格的接口的灵活性与类的功能结合在一起. 考虑原则上的多重继承.

Pattern Matching

考虑"切换"类固醇. 与类层次结构,序列等进行匹配.

Higher-order functions

函数是一流的对象. 以保证类型安全的方式编写它们. 在任何地方使用它们,并将它们传递给任何东西.

Traits
abstract class Spacecraft {
  def engage(): Unit
}
trait CommandoBridge extends Spacecraft {
  def engage(): Unit = {
    for (_ <- 1 to 3)
      speedUp()
  }
  def speedUp(): Unit
}
trait PulseEngine extends Spacecraft {
  val maxPulse: Int
  var currentPulse: Int = 0
  def speedUp(): Unit = {
    if (currentPulse < maxPulse)
      currentPulse += 1
  }
}
class StarCruiser extends Spacecraft
                     with CommandoBridge
                     with PulseEngine {
  val maxPulse = 200
}

Flexibly Combine Interface & Behavior

In Scala, 多重特征 can be mixed into a class to combine their interface and their behavior.

在这里, StarCruiser是一艘Spacecraft ,它的CommandoBridge知道如何与飞船接合(提供了加速的手段),而PulseEngine则指定了如何加速.

Switch on the structure of your data

在Scala中, 案例类用于表示结构数据类型. 他们隐式地为类提供了有意义的toStringequalshashCode方法,以及通过模式匹配进行解构的能力.


在此示例中,我们定义了一小堆案例类,它们代表整数的二进制树(此处为简单起见,省略了通用版本). 在inOrdermatch构造根据t的类型选择正确的分支,同时解构Node的参数.

模式匹配
// Define a set of case classes for representing binary trees.
sealed abstract class Tree
case class Node(elem: Int, left: Tree, right: Tree) extends Tree
case object Leaf extends Tree

// Return the in-order traversal sequence of a given tree.
def inOrder(t: Tree): List[Int] = t match {
  case Node(e, l, r) => inOrder(l) ::: List(e) ::: inOrder(r)
  case Leaf          => List()
}

Go Functional with Higher-Order Functions

在Scala中,函数是值,可以使用简洁的语法将其定义为匿名函数.

Scala
val people: Array[Person]

// Partition `people` into two arrays `minors` and `adults`.
// Use the anonymous function `(_.age < 18)` as a predicate for partitioning.
val (minors, adults) = people partition (_.age < 18)
Java
List<Person> people;

List<Person> minors = new ArrayList<Person>(people.size());
List<Person> adults = new ArrayList<Person>(people.size());
for (Person person : people) {
    if (person.getAge() < 18)
        minors.add(person);
    else
        adults.add(person);
}

Run Scala in your browser

Scastie是您浏览器中的Scala + sbt ! 您可以使用任何版本的Scala,甚至可以使用备用后端,例如Dotty,Scala.js,Scala Native和Typelevel Scala. 您可以使用任何已发布的库. 您可以与任何人保存和共享Scala程序/内部版本.

交互运行Scala代码

Online Courses

Functional Programming Principles in Scala

  • 免费(可选的付费证书)
  • 每两周开始新的会话!

Functional Program Design in Scala

  • 免费(可选的付费证书)
  • 每两周开始新的会话!

Parallel Programming

  • 免费(可选的付费证书)
  • 每两周开始新的会话!

Big Data Analysis with Scala and Spark

  • 免费(可选的付费证书)
  • New sessions starting every 2 weeks!

Functional Programming in Scala Capstone

  • 免费(可选的付费证书)
  • 每两周开始新的会话!

Programming Reactive Systems

  • 免费(可选的付费证书)
  • 2019年2月18日

Upcoming Training

Scala ecosystem

Scala库索引(或Scaladex)表示所有已发布的Scala库的地图. 使用Scaladex,开发人员现在可以查询超过175,000个Scala库版本. Scaladex得到Scala中心的正式支持.

The Scala Library Index

What’s New

BLOG

Better management of transitive dependencies and conflicts

2019年10月17日星期四

2019年初,Scala中心顾问委员会接受了Spotify的提议 ,其目标是改善对sbt依赖管理中冲突的处理.

在以下情况下,我们正在进行的工作可能会引起您的兴趣:

  • 您遇到了依赖项之间的版本冲突的麻烦,并且不知道该怎么办或在哪里寻求建议.
  • 您需要更多控制版本冲突的方式.
  • 您需要自动帮助来确定版本升级是否会破坏项目中的某些内容.

在我们开始该项目时,默认情况下仍使用Ivy来解析sbt中的库,但仍在努力使用coursier,因此我们将重点放在后者上,以作为改进的工具. 从那时起,sbt中的coursier支持成为正式支持,并且默认情况下在sbt 1.3.0中提供. 除了具有比以前在sbt或Ivy中使用的模型更简单的模型外,coursier还具有可从命令行使用的优点,并且可以使coursier API的其他用户受益.

关于静态分析的第三点,我们发现 Maven 的missinglink工具该工具源自Spotify本身. 该工具可以分析Maven项目的类路径,并提前(在"链接"时间)检测在运行时是否会遇到二进制不兼容问题. 唯一的问题是,它无法从sbt中使用,从而使它对于大量的Scala用户无效. 我们构建并发布了一个用于缺少链接的sbt插件来解决此漏洞.

Version ordering and reconciliation

尽管大多数人对库的解析有一个简单的直觉(库的一个新版本被一个旧的版本所取代),但是如何比较和协调版本的细节却非常复杂. 我们在coursier网站上提供了专门的文档页面 ,以帮助用户了解在不太重要的情况下解决方案的工作原理. 为了改善从sbt 1.2.x和基于Ivy的分辨率升级的体验,我们 Eugene Yokota的帮助下对了Coursier 2.0.0-RC3-4中的分辨率进行了调整 ,使其更符合以前的sbt行为Ivy,和语义版本规范 . 文档页面应尽快进行相应更新.

最重要的是,Eugene Yokota最近写了一篇博客文章,比较了在Ivy和Coursier中如何比较和协调版本.

Strict conflict manager

默认情况下,Ivy和Coursier都允许依赖图包含两个不同版本的库,在这种情况下,他们会选择胜者. 有时,我们需要更多的控制权,而不希望发生任何冲突解决方案. 相反,如果一个库有两个不同的版本,我们希望报告一个错误. 严格的冲突管理者恰恰做到了这一点,因此我们增加了一位顾问. 以下说明用于启用严格冲突管理器:1)在sbt构建中,以及2)从coursier命令行中.

sbt

从SBT,可以启用严格的冲突管理者通过原conflictManager关键,像

conflictManager := ConflictManager.strict

或者,如果sbt-coursier与之相伴,则可能以更细粒度的方式启用它

versionReconciliation += "*" % "*" % "strict"

(请注意,要在sbt 1.3.x项目中使用sbt-coursier,则需要基于coursier的sbt启动器 .可通过其自定义sbt-extras coursier bootstrap sbt-launcher && ./sbt获取它,或使用coursier bootstrap sbt-launcher && ./sbt生成一个.)

只有通过严格检查, update任务才能成功. 如果不这样做,则可以使用dependencyOverrides强制使用错误的依赖版本,例如

dependencyOverrides += "org.typelevel" % "cats-core_2.12" % "1.5.0"

或调整其版本对帐,例如

versionReconciliation ++= Seq(
  "org.typelevel" %% "cats-core" % "relaxed", // "semver" reconciliation is also available
  "*" % "*" % "strict"
)

有许多版本对帐类型:

  • "strict"要求所有受抚养人都依赖于确切的选定版本(如果他们依赖于一个间隔,则只需要在其中包含选定的版本)
  • "semver"要求所有受抚养人依赖于与所选版本相同的主要版本(如果他们依赖于一个间隔,则也只需将所选版本包含在其中)
  • "default"是coursier中的默认版本协调,可在coursier CLI或sbt-coursier插件中启用. 此页将对此进行更详细的描述.
  • "relaxed"不会触发任何冲突. 它是sbt 1.3.x的coursier支持中的默认设置,它可以更好地与以前的sbt版本兼容. 它会忽略最低版本和版本间隔,直到可以使用与"default"相同的算法对它们进行协调.

由于可以根据每个工件或每个组织设置对帐策略,因此以声明的方式告诉sbt变得容易得多,例如,某些项目符合SemVer,并且可以根据SemVer解决对该特定项目的依赖关系,但不是其他.

CLI

在命令行中,我们可以将新的coursier严格冲突管理器与以下命令配合使用:

$ coursier resolve --strict \
    org.typelevel:cats-effect_2.12:2.0.0 \
    org.typelevel:cats-core_2.12:1.5.0
Resolution error: Unsatisfied rule Strict(*:*): Found evicted dependencies:

org.typelevel:cats-core_2.12:2.0.0 (1.5.0 wanted)
└─ org.typelevel:cats-core_2.12:1.5.0

要忽略一些严格的检查,您可以使用

$ coursier resolve \
    --strict-exclude 'org.typelevel:cats-core*' \
    org.typelevel:cats-effect_2.12:2.0.0 \
    org.typelevel:cats-core_2.12:1.5.0
org.scala-lang:scala-library:2.12.9:default
org.typelevel:cats-core_2.12:2.0.0:default
org.typelevel:cats-effect_2.12:2.0.0:default
org.typelevel:cats-kernel_2.12:2.0.0:default
org.typelevel:cats-macros_2.12:2.0.0:default

(传递--strict-exclude自动启用--strict ),或仅在严格检查中包括一部分依赖项,例如

$ coursier resolve \
    --strict-include 'org.scala-lang:*' \
    org.typelevel:cats-effect_2.12:2.0.0 \
    org.typelevel:cats-core_2.12:1.5.0
org.scala-lang:scala-library:2.12.9:default
org.typelevel:cats-core_2.12:2.0.0:default
org.typelevel:cats-effect_2.12:2.0.0:default
org.typelevel:cats-kernel_2.12:2.0.0:default
org.typelevel:cats-macros_2.12:2.0.0:default

另外,强制错误的依赖版本会导致严格检查忽略它:

$ coursier resolve \
    --strict \
    --strict-exclude 'org.scala-lang:*' \
    --force-version org.typelevel:cats-core_2.12:1.5.0 \
    org.typelevel:cats-effect_2.12:2.0.0 \
    org.typelevel:cats-core_2.12:1.5.0
org.scala-lang:scala-library:2.12.9:default
org.scala-lang:scala-reflect:2.12.6:default
org.typelevel:cats-core_2.12:1.5.0:default
org.typelevel:cats-effect_2.12:2.0.0:default
org.typelevel:cats-kernel_2.12:1.5.0:default
org.typelevel:cats-macros_2.12:1.5.0:default
org.typelevel:machinist_2.12:0.6.6:default

Static analysis checks

为了利用sbt项目中missinglink库提供的静态分析的功能 ,我们开发了sbt-missinglink . 自述文件解释了如何使用它,但是基础很简单.

首先,在project/plugins.sbt添加以下行:

addSbtPlugin("ch.epfl.scala" % "sbt-missinglink" % "0.1.0")

然后只需为要测试的项目运行以下任务:

> theProject/missinglinkCheck

假设已全部调用Compile配置的方法(在src/main/ ),这将检查项目的传递依赖项是否没有任何二进制兼容性冲突. 例如,您可以将该任务添加到CI脚本中.

如果检查成功,则可以保证在运行时不会发生LinkageError ,除非涉及运行时反射,从而使静态分析变得不可能.

该插件目前非常简单,将进行扩展以支持missinglink更多功能,尤其是能够在执行的检查中添加排除项的功能. 如果missinglink本身不足以满足Scala开发人员的需求,那么我们将来可能还会对此做出改进.

Conclusion

我们已经看到了一些新方法,可以改善对传递依赖项的管理. 特别是,我们介绍了:

  • 和解策略,可让您声明性地指定各个库的兼容性保证,从而使调查员可以更好地,更安全地解决冲突,并且
  • sbt-missinglink ,一个sbt插件,可以轻松地提前检查您已解决的传递依赖项实际上是二进制兼容的.

Twitter Feed

查看更多推文,或

Follow Scala on twitter

The Scala language is maintained by

  • Scala Center
  • Lightbend

Scala Center is supported by

EPFL IBM Verizon Goldman Sachs 47 Degrees SAP Twitter Your company