Scala

Scala


Scala (/?skɑ?l?/ SKAH-lah)[8] is a strong statically typed general-purpose programming language which supports both object-oriented programming and functional programming. Designed to be concise,[9] many of Scala's design decisions are aimed to address criticisms of Java.[7

Scala source code can be compiled to Java bytecode and run on a Java virtual machine (JVM). Scala can also be compiled to JavaScript to run in a browser, or directly to a native executable. On the JVM Scala provides language interoperability with Java so that libraries written in either language may be referenced directly in Scala or Java code.[10] Like Java, Scala is object-oriented, and uses a syntax termed curly-brace which is similar to the language C. Since Scala 3, there is also an option to use the off-side rule (indenting) to structure blocks, and its use is advised. Martin Odersky has said that this turned out to be the most productive change introduced in Scala 3.[11]

Unlike Java, Scala has many features of functional programming languages (like Scheme, Standard ML, and Haskell), including currying, immutability, lazy evaluation, and pattern matching. It also has an advanced type system supporting algebraic data types, covariance and contravariance, higher-order types (but not higher-rank types), anonymous types, operator overloading, optional parameters, named parameters, raw strings, and an experimental exception-only version of algebraic effects that can be seen as a more powerful version of Java's checked exceptions.[12]

The name Scala is a portmanteau of scalable and language, signifying that it is designed to grow with the demands of its users.[13]

Contents
1	History
2	Platforms and license
2.1	Other compilers and targets
3	Examples
3.1	"Hello World" example
3.2	Basic example
3.3	Example with classes
4	Features (with reference to Java)
4.1	Syntactic flexibility
4.2	Unified type system
4.3	For-expressions
4.4	Functional tendencies
4.4.1	Everything is an expression
4.4.2	Type inference
4.4.3	Anonymous functions
4.4.4	Immutability
4.4.5	Lazy (non-strict) evaluation
4.4.6	Tail recursion
4.4.7	Case classes and pattern matching
4.4.8	Partial functions
4.5	Object-oriented extensions
4.6	Expressive type system
4.7	Type enrichment
5	Concurrency
6	Cluster computing
7	Testing
8	Versions
9	Comparison with other JVM languages
10	Adoption
10.1	Language rankings
10.2	Companies
11	Criticism
12	See also
13	References
14	Further reading
History[edit]

The design of Scala started in 2001 at the école Polytechnique Fédérale de Lausanne (EPFL) (in Lausanne, Switzerland) by Martin Odersky. It followed on from work on Funnel, a programming language combining ideas from functional programming and Petri nets.[14] Odersky formerly worked on Generic Java, and javac, Sun's Java compiler.[14]

After an internal release in late 2003, Scala was released publicly in early 2004 on the Java platform,[15][7][14][16] A second version (v2.0) followed in March 2006.[7]

On 17 January 2011, the Scala team won a five-year research grant of over €2.3 million from the European Research Council.[17] On 12 May 2011, Odersky and collaborators launched Typesafe Inc. (later renamed Lightbend Inc.), a company to provide commercial support, training, and services for Scala. Typesafe received a $3 million investment in 2011 from Greylock Partners.[18][19][20][21]

Platforms and license[edit]

Scala runs on the Java platform (Java virtual machine) and is compatible with existing Java programs.[15] As Android applications are typically written in Java and translated from Java bytecode into Dalvik bytecode (which may be further translated to native machine code during installation) when packaged, Scala's Java compatibility makes it well-suited to Android development, more so when a functional approach is preferred.[22]

The reference Scala software distribution, including compiler and libraries, is released under the Apache license.[23]

Other compilers and targets[edit]

Scala.js is a Scala compiler that compiles to JavaScript, making it possible to write Scala programs that can run in web browsers or Node.js.[24] The compiler, in development since 2013, was announced as no longer experimental in 2015 (v0.6). Version v1.0.0-M1 was released in June 2018 and version 1.1.1 in September 2020.[25]

Scala Native is a Scala compiler that targets the LLVM compiler infrastructure to create executable code that uses a lightweight managed runtime, which uses the Boehm garbage collector. The project is led by Denys Shabalin and had its first release, 0.1, on 14 March 2017. Development of Scala Native began in 2015 with a goal of being faster than just-in-time compilation for the JVM by eliminating the initial runtime compilation of code and also providing the ability to call native routines directly.[26][27]

A reference Scala compiler targeting the .NET Framework and its Common Language Runtime was released in June 2004,[14] but was officially dropped in 2012.[28]

Examples[edit]
"Hello World" example[edit]

The Hello World program written in Scala 3 has this form:

@main def main() = println("Hello, World!")


Unlike the stand-alone Hello World application for Java, there is no class declaration and nothing is declared to be static; a singleton object created with the object keyword is used instead.

When the program is stored in file HelloWorld.scala, the user compiles it with the command:

$ scalac HelloWorld.scala


and runs it with

$ scala HelloWorld


This is analogous to the process for compiling and running Java code. Indeed, Scala's compiling and executing model is identical to that of Java, making it compatible with Java build tools such as Apache Ant.

A shorter version of the "Hello World" Scala program is:

println("Hello, World!")


Scala includes an interactive shell and scripting support.[29] Saved in a file named HelloWorld2.scala, this can be run as a script using the command:

$ scala HelloWorld2.scala


Commands can also be entered directly into the Scala interpreter, using the option -e:

$ scala -e 'println("Hello, World!")'


Expressions can be entered interactively in the REPL:

$ scala
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.

scala> List(1, 2, 3).map(x => x * x)
res0: List[Int] = List(1, 4, 9)

scala>

Basic example[edit]

The following example shows the differences between Java and Scala syntax. The function mathFunction takes an integer, squares it, and then adds the cube root of that number to the natural log of that number, returning the result (i.e., ):

// Java:
int mathFunction(int num) {
    int numSquare = num*num;
    return (int) (Math.cbrt(numSquare) +
      Math.log(numSquare));
}



// Scala: Direct conversion from Java

// no import needed; scala.math
// already imported as `math`
def mathFunction(num: Int): Int = {
  var numSquare: Int = num*num
  return (math.cbrt(numSquare) + math.log(numSquare)).
    asInstanceOf[Int]
}

	
// Scala: More idiomatic
// Uses type inference, omits `return` statement,
// uses `toInt` method, declares numSquare immutable

import math._
def mathFunction(num: Int) = {
  val numSquare = num*num
  (cbrt(numSquare) + log(numSquare)).toInt
}


Some syntactic differences in this code are:

Scala does not require semicolons to end statements.
Value types are capitalized: Int, Double, Boolean instead of int, double, boolean.
Parameter and return types follow, as in Pascal, rather than precede as in C.
Methods must be preceded by def.
Local or class variables must be preceded by val (indicates an immutable variable) or var (indicates a mutable variable).
The return operator is unnecessary in a function (although allowed); the value of the last executed statement or expression is normally the function's value.
Instead of the Java cast operator (Type) foo, Scala uses foo.asInstanceOf[Type], or a specialized function such as toDouble or toInt.
Instead of Java's import foo.*;, Scala uses import foo._.
Function or method foo() can also be called as just foo; method thread.send(signo) can also be called as just thread send signo; and method foo.toString() can also be called as just foo toString.

These syntactic relaxations are designed to allow support for domain-specific languages.

Some other basic syntactic differences:

Array references are written like function calls, e.g. array(i) rather than array[i]. (Internally in Scala, the former expands into array.apply(i) which returns the reference)
Generic types are written as e.g. List[String] rather than Java's List<String>.
Instead of the pseudo-type void, Scala has the actual singleton class Unit (see below).
Example with classes[edit]

The following example[clarification needed (see talk)] contrasts the definition of classes in Java and Scala.

// Java:
public class Point {
  private double x, y;
  public Point(final double x, final double y) {
    this.x = x;
    this.y = y;
  }

  public Point(
    double x, double y,
    boolean addToGrid
  ) {
    this(x, y);

    if (addToGrid)
      grid.addToGrid(this);
  }

  public Point() {
    this(0.0, 0.0);
  }

  private void addToGrid(Point p) {
      x += p.x;
      y += p.y;
  }

  public double getX() {
    return x;
  }

  public double getY() {
    return y;
  }

  double distanceToPoint(final Point other) {
    return distanceBetweenPoints(x, y,
      other.x, other.y);
  }

  private static Point grid = new Point();

  static double distanceBetweenPoints(
      final double x1, final double y1,
      final double x2, final double y2
  ) {
    return Math.hypot(x1 - x2, y1 - y2);
  }
}

	
// Scala
class Point(
    val x: Double, val y: Double,
    addToGrid: Boolean = false
) {
  import Point._

  if (addToGrid)
    grid.addToGrid(this)

  def this() = this(0.0, 0.0)

  def distanceToPoint(other: Point) =
    distanceBetweenPoints(x, y, other.x, other.y)
}

object Point {
  private val grid = new Point()

  def distanceBetweenPoints(x1: Double, y1: Double,
      x2: Double, y2: Double) = {
    math.hypot(x1 - x2, y1 - y2)
  }
}


The code above shows some of the conceptual differences between Java and Scala's handling of classes:

Scala has no static variables or methods. Instead, it has singleton objects, which are essentially classes with only one instance. Singleton objects are declared using object instead of class. It is common to place static variables and methods in a singleton object with the same name as the class name, which is then known as a companion object.[15] (The underlying class for the singleton object has a $ appended. Hence, for class Foo with companion object object Foo, under the hood there's a class Foo$ containing the companion object's code, and one object of this class is created, using the singleton pattern.)
In place of constructor parameters, Scala has class parameters, which are placed on the class, similar to parameters to a function. When declared with a val or var modifier, fields are also defined with the same name, and automatically initialized from the class parameters. (Under the hood, external access to public fields always goes through accessor (getter) and mutator (setter) methods, which are automatically created. The accessor function has the same name as the field, which is why it's unnecessary in the above example to explicitly declare accessor methods.) Note that alternative constructors can also be declared, as in Java. Code that would go into the default constructor (other than initializing the member variables) goes directly at class level.
Default visibility in Scala is public.
Features (with reference to Java)[edit]

Scala has the same compiling model as Java and C#, namely separate compiling and dynamic class loading, so that Scala code can call Java libraries.

Scala's operational characteristics are the same as Java's. The Scala compiler generates byte code that is nearly identical to that generated by the Java compiler.[15] In fact, Scala code can be decompiled to readable Java code, with the exception of certain constructor operations. To the Java virtual machine (JVM), Scala code and Java code are indistinguishable. The only difference is one extra runtime library, scala-library.jar.[30]

Scala adds a large number of features compared with Java, and has some fundamental differences in its underlying model of expressions and types, which make the language theoretically cleaner and eliminate several corner cases in Java. From the Scala perspective, this is practically important because several added features in Scala are also available in C#.

Syntactic flexibility[edit]

As mentioned above, Scala has a good deal of syntactic flexibility, compared with Java. The following are some examples:

Semicolons are unnecessary; lines are automatically joined if they begin or end with a token that cannot normally come in this position, or if there are unclosed parentheses or brackets.
Any method can be used as an infix operator, e.g. "%d apples".format(num) and "%d apples" format num are equivalent. In fact, arithmetic operators like + and << are treated just like any other methods, since function names are allowed to consist of sequences of arbitrary symbols (with a few exceptions made for things like parens, brackets and braces that must be handled specially); the only special treatment that such symbol-named methods undergo concerns the handling of precedence.
Methods apply and update have syntactic short forms. foo()—where foo is a value (singleton object or class instance)—is short for foo.apply(), and foo() = 42 is short for foo.update(42). Similarly, foo(42) is short for foo.apply(42), and foo(4) = 2 is short for foo.update(4, 2). This is used for collection classes and extends to many other cases, such as STM cells.
Scala distinguishes between no-parens (def foo = 42) and empty-parens (def foo() = 42) methods. When calling an empty-parens method, the parentheses may be omitted, which is useful when calling into Java libraries that do not know this distinction, e.g., using foo.toString instead of foo.toString(). By convention, a method should be defined with empty-parens when it performs side effects.
Method names ending in colon (:) expect the argument on the left-hand-side and the receiver on the right-hand-side. For example, the 4 :: 2 :: Nil is the same as Nil.::(2).::(4), the first form corresponding visually to the result (a list with first element 4 and second element 2).
Class body variables can be transparently implemented as separate getter and setter methods. For trait FooLike { var bar: Int }, an implementation may be object Foo extends FooLike { private var x = 0; def bar = x; def bar_=(value: Int) { x = value }} } }. The call site will still be able to use a concise foo.bar = 42.
The use of curly braces instead of parentheses is allowed in method calls. This allows pure library implementations of new control structures.[31] For example, breakable { ... if (...) break() ... } looks as if breakable was a language defined keyword, but really is just a method taking a thunk argument. Methods that take thunks or functions often place these in a second parameter list, allowing to mix parentheses and curly braces syntax: Vector.fill(4) { math.random } is the same as Vector.fill(4)(math.random). The curly braces variant allows the expression to span multiple lines.
For-expressions (explained further down) can accommodate any type that defines monadic methods such as map, flatMap and filter.

By themselves, these may seem like questionable choices, but collectively they serve the purpose of allowing domain-specific languages to be defined in Scala without needing to extend the compiler. For example, Erlang's special syntax for sending a message to an actor, i.e. actor ! message can be (and is) implemented in a Scala library without needing language extensions.

Unified type system[edit]

Java makes a sharp distinction between primitive types (e.g. int and boolean) and reference types (any class). Only reference types are part of the inheritance scheme, deriving from java.lang.Object. In Scala, all types inherit from a top-level class Any, whose immediate children are AnyVal (value types, such as Int and Boolean) and AnyRef (reference types, as in Java). This means that the Java distinction between primitive types and boxed types (e.g. int vs. Integer) is not present in Scala; boxing and unboxing is completely transparent to the user. Scala 2.10 allows for new value types to be defined by the user.

For-expressions[edit]

Instead of the Java "foreach" loops for looping through an iterator, Scala has for-expressions, which are similar to list comprehensions in languages such as Haskell, or a combination of list comprehensions and generator expressions in Python. For-expressions using the yield keyword allow a new collection to be generated by iterating over an existing one, returning a new collection of the same type. They are translated by the compiler into a series of map, flatMap and filter calls. Where yield is not used, the code approximates to an imperative-style loop, by translating to foreach.

A simple example is:

val s = for (x <- 1 to 25 if x*x > 50) yield 2*x


The result of running it is the following vector:

Vector(16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50)

(Note that the expression 1 to 25 is not special syntax. The method to is rather defined in the standard Scala library as an extension method on integers, using a technique known as implicit conversions[32] that allows new methods to be added to existing types.)

A more complex example of iterating over a map is:

// Given a map specifying Twitter users mentioned in a set of tweets,
// and number of times each user was mentioned, look up the users
// in a map of known politicians, and return a new map giving only the
// Democratic politicians (as objects, rather than strings).
val dem_mentions = for {
    (mention, times) <- mentions
    account          <- accounts.get(mention)
    if account.party == "Democratic"
  } yield (account, times)


Expression (mention, times) <- mentions is an example of pattern matching (see below). Iterating over a map returns a set of key-value tuples, and pattern-matching allows the tuples to easily be destructured into separate variables for the key and value. Similarly, the result of the comprehension also returns key-value tuples, which are automatically built back up into a map because the source object (from the variable mentions) is a map. Note that if mentions instead held a list, set, array or other collection of tuples, exactly the same code above would yield a new collection of the same type.

Functional tendencies[edit]

While supporting all of the object-oriented features available in Java (and in fact, augmenting them in various ways), Scala also provides a large number of capabilities that are normally found only in functional programming languages. Together, these features allow Scala programs to be written in an almost completely functional style and also allow functional and object-oriented styles to be mixed.

Examples are:

No distinction between statements and expressions
Type inference
Anonymous functions with capturing semantics (i.e., closures)
Immutable variables and objects
Lazy evaluation
Delimited continuations (since 2.8)
Higher-order functions
Nested functions
Currying
Pattern matching
Algebraic data types (through case classes)
Tuples]

要查看或添加评论,请登录

Darshika Srivastava的更多文章

  • METADATA

    METADATA

    WHAT IS METADATA? Often referred to as data that describes other data, metadata is structured reference data that helps…

  • SSL

    SSL

    What is SSL? SSL, or Secure Sockets Layer, is an encryption-based Internet security protocol. It was first developed by…

  • BLOATWARE

    BLOATWARE

    What is bloatware? How to identify and remove it Unwanted pre-installed software -- also known as bloatware -- has long…

  • Data Democratization

    Data Democratization

    What is Data Democratization? Unlocking the Power of Data Cultures For Businesses Data is a vital asset in today's…

  • Rooting

    Rooting

    What is Rooting? Rooting is the process by which users of Android devices can attain privileged control (known as root…

  • Data Strategy

    Data Strategy

    What is a Data Strategy? A data strategy is a long-term plan that defines the technology, processes, people, and rules…

  • Product

    Product

    What is the Definition of Product? Ask a few people that question, and their specific answers will vary, but they’ll…

  • API

    API

    What is an API? APIs are mechanisms that enable two software components to communicate with each other using a set of…

  • Apple Intelligence

    Apple Intelligence

    What Is Apple Intelligence? Apple Intelligence is an artificial intelligence developed by Apple Inc. Relying on a…

  • Snowflake

    Snowflake

    What is the Snowflake Data Platform? While data is a core asset for modern enterprises, technology’s ability to scale…

社区洞察

其他会员也浏览了