标签:
Scala runs on the JVM and can directly call and be called from Java, but source compatibility was not a goal. Scala has a lot of capabilities not in Java, and to help those new features work more nicely, there are a number of differences between Java and Scala syntax that can make reading Scala code a bit of a challenge for Java programmers when first encountering Scala. This primer attempts to explain those differences. It is aimed at Java programmers, so some details about syntax which are the same as Java are omitted.
This primer is not intended to be a complete tutorial on Scala,
rather it is more of a syntax reference.
For a much better introduction to the language,
you should buy the book
Programming in Scala by Martin Odersky, Lex Spoon and Bill Venners.
Most of these syntax differences can be explained by two of Scala‘s
major goals:
The logic behind some of these syntax rules may at first seem arbitrary, but the rules support each other surprisingly well. Hopefully by the time you finish this primer, you will have no trouble understanding code fragments like this one:
Scala is an integrated object/functional language. In the discussion below, the terms "method" and "function" are used interchangeably.
You can run the Scala interpreter and type in these examples
to get a better feel for how these rules work.
class
and an object of the same name and want them to
be companions, in which case they must be in the same file.
123.toString() is valid.
val or
var keyword can be converted to a function definition
simply by replacing that keyword with the def keyword.
The syntax at the calling sites does not change.
scala.xml.Elem to val x:
@ character.static keyword. Methods and variables that you would declare static in Java go into an object rather than a class in Scala. Objects are singletons.break or continue statements. Fortunately, Scala‘s support of a functional programming style reduces the need for these.protected and private can include a scope in square brackets, such as private[this] or protected[MyPackage1.MyPackage2]. The default access is public.val keyword declares an immutable value (a val), similar to the final keyword in Java. The var keyword declares a mutable variable.import statement:
java.util.Date and java.sql.Date and be able to use them both without having to type the whole qualified name each time, you could do this:
_, that symbol will not be imported. This allows importing everything except a specified symbol:
abstract keyword is only used for abstract classes and traits. To declare an abstract function (def), val, variable (var), or type, you omit the = character and body of the item.override modifier must be specified. Overriding a method without using the override modifier or using the modifier when not overriding a superclass method will result in compilation error.lazy, implicitscala.xml.Elem class. Note that "abc\"def" is a seven character String with a double quote in the middle, but if abc is an instance of scala.xml.Elem, then abc\"def" is a call passing a three character String to the backslash method, a method that accepts a String argument and returns an instance of scala.xml.NodeSeq.import statement or in a case statement to represent a "don‘t care" value. This is because asterisk is a valid symbol character in Scala.case statement, that difference is used to disambiguate between a constant value, such as PI if Math.PI has been imported (starts with upper case) and a placeholder name being introduced (whose scope is then limited to the body of the case statement).5 * { val a = 1; a + 2 } is valid and yields the value 15.*^ and +^, the *^ will have higher precedence. The one exception to this rule is that if the operator ends with an equal sign (=) and is not one of the standard relational operators, then it will have the same precedence as simple assignment.unary_+, unary_- etc.?: ternary operator in Scala. Instead, you use a standard if/then/else statement:
case statement to allow selecting one possible code path from many based on a value. A simple switch statement in Java might look like this:
switch keyword as in Java, Scala uses a match expression. The match keyword comes after the value being matched, unlike the relative positions of the switch keyword and the value in Java.match works on all types, not just ints. For example, you can match on a String variable and have case statements each with a constant String value.break statement is required, and execution does not fall through to the next case.match statements return values. The value of a match statement is the value of whichever branch was executed.case expression can include patterns, which allow for more complex matching. Case matching is handled by extractors, which can be implemented by writing an unapply method in an object.case pattern can include a variable declaration with a type, in which case the variable is defined with that type and set to the value of the matched data within the body of that case.
@ character before the pattern:
if followed by a boolean expression:
b gets set to whatever is inside the body element if there is only one element there:
_* to match any sequence:
catch block of a try/catch statement uses the same syntax as the body of a match statement:
<- operator in a generator in a for expression.For Expressions are also called For Comprehensions.
for expression consists of the for keyword, a sequence of specific kinds of elements separated by semicolons or newlines and surrounded by parentheses, and the yield keyword followed by an expression:
n <- 0 to 6, which produces multiple values and assigns them to a new val (here n). The new val name appears to the left of the <- operator; to the right of that operator is a value which implements the foreach method to generate a series of values.e = n%2, which introduces a new value by performing the specified calculation.if e==0, which filters out the values which do not satisfy that expression.for expression is the same as the type of the first generator.yield followed by an expression, you can omit the yield keyword and use a block of code in place of a single expression.for statement can always be translated into a series of foreach, filter, map and flatMap method calls. In that sense, the for statement is syntactic sugar.apply method.arr(index) is converted to arr.apply(index).arr(index) = newval is converted to arr.update(index,newval).Array keyword and with the element type in square brackets, rather than using empty square brackets after a type as is done in Java. For example, an array with space for three Strings would be declared like this:
Tuple2[Int,String].Pair object allows that word to be used instead of Tuple2 for building and matching two element Tuples.Triple object allows that word to be used instead of Tuple3 for building and matching three element Tuples.(1, 2, "foo") is a Tuple3[Int,Int,String].-> operator, which works on any value: "a" -> 25 is the same as ("a", 25). The following expression is true:
Any to Predef.ArrowAssoc, which contains the -> method.tens and 8 to the new val ones.
val to make them immutable instance values (vals), or by var to make them instance variables.private or protected. By default, class parameters using val or var are public.private before the parameter list.trait is like interface in Java, but can include implementation code. Classes in Scala don‘t implement traits, they extend them same as classes. If a class extends multiple traits, or extends a class plus traits, the keyword with is used rather than commas as in Java.case keyword before the class keyword. This automatically does the equivalent of the following:
val to all parameters, making them immutable instance values.equals and hashCode methods so that instances of that class can safely be used in collections.object of the same name with an apply method with the same args as declared for the class, to allow creation of instances without using the new keyword, and with an unapply method to allow the class name to be used as an extractor in case statements.isInstanceOf method is used to determine if an object is an instance of a specific class:
isInstanceOf, a value can be cast to a specific type by using the type-parameterized asInstanceOf method:
case statement, which simultaneously tests for a type and sets a new value of that type:
isInstanceOf method can be used to test if an object matches a trait as well as a class. It can also be used to test an instance against a structural definition, which can be used to test if an instance implements a specific method:
classOf[MyClass] as opposed to MyClass.class as in Java.Int and all doubles are of type Double. (In previous versions of Scala, either upper case Int or lower case int was accepted, but convention now is to use only the upper case version, and this may be enforced by the compiler in the future.)name:type rather than type name as in Java. This is to allow the type to be omitted in many cases, since Scala does type inference. For example, write n:Int rather than int n.[T] rather than in angle brackets <T> as in Java. Thus a generic type might be specified as F[A,B,C].F[+A,-B] means F is qualified by a covariant type A and a contravariant type B.T<:U means type U is an upper bound for T, whereas T>:U means type U is a lower bound for type T.T<%U means type U is a view bound for T, which allows for implicit conversion to T and can thus support more actual types.Pair[String,Int], can be written in infix notation by placing the higher kinded type name between its two type qualifiers, such as String Pair Int. This makes more sense if the higher kinded type name happens to use operator characters such as +. Thus when you see a type such as Quantity[M + M2], as used in the Quantity class in this file, that is the same as Quantity[+[M,M2]], so look for a type called + that takes two type qualifiers.? wildcard type.type T in an existential type specification can be replaced by a more complex expression:
type keyword. Similar to a typedef in C, the type variable simplifies code when a complicated type is used many times:
this, but optionally using a different name in place of this:
Outer#Inner to refer generically to that inner class. If you had an instance x of class Outer, you would refer to the specific class Inner in that instance by using x.Inner, which is a distinct type from the Inner class within any other instance of Outer, and a subtype of the generic Outer#Inner class.Unit rather than void as in Java. If a function never returns (such as if it always throws a Throwable) the return type is Nothing.args parameter would have the type Array[Any] within the body of the printf function.apply method, foo(bar) (where foo is an instance of that class) translates to foo.apply(bar).
Foo(bar) that is most likely a call to the apply method of object Foo.apply method can be overloaded, with different versions having different signatures.unapply in an object definition is also treated specially: it is invoked as an extractor when the object name is used in a case statement pattern.length() function on String can be invoked as "abc".length rather than "abc".length(). If the function is a Scala function defined without parentheses, then the function must be called without parentheses."Syntactic sugar" is added syntax to make certain constructs easier or more natural to specify. The step in which the compiler replaces these constructs by their more verbose equivalents is called "desugaring".
Function1[A,B], functions with two parameters are of type Function2[A,B,C], etc. The last type in the list of parameter types is the return value type, so there is always one more than the number N of parameters. A function with no parameters is an instance of Function0[A]. The name Function with no number is equivalent to Function1.(A,B)=>C is shorthand ("syntactic sugar") for Function2[A,B,C].Function1[A,B] can be written as (A)=>B, or as just A=>B.Function0[A] (i.e. a function with no parameters) can be written as ()=>A. This function can be called with or without parentheses (as mentioned in the Function Definition section).=>A. This function must be called without parentheses. If you are declaring a variable x of this type, the declaration looks like x: =>A. This signature is often used for call-by-name parameters.list):
/: (which also does a foldLeft):
/: operator is equivalent to the foldLeft method (the List class defines both methods).foldLeft method (and the equivalent /: operator method) uses a curried parameter list, with the first parameter list having only one method. This allows us to take advantage of the next step.foldLeft method takes only one parameter (in the first parameter list), we can invoke it without the dot and parentheses.list object goes on the right and the 0 argument goes on the left.compose function with three type parameters A, B and C. The regular function parameters are in parentheses.f is a function that takes one argument of type B and returns a value of type C. The parameter g is also a function.compose function, which appears after the colon that follows the parentheses, is a function that takes one argument of type A and returns a value of type C.= character, and is a function which has a parameter a of type A and returns the value f(g(a)).compose function does NOT execute functions f and g, but rather returns a function object which, when invoked, will execute f(g) on its argument.Updated 2008-10-19: added classOf, added infix type notation.
标签:
原文地址:http://www.cnblogs.com/jvava/p/4621071.html