A few very simple characteristics of the Scala language. No Spark specifics yet.
Mostly taken from A short primer on Scala. See also additional documentation in Scala overviews and the Scala cheatsheet
In terms of general syntax, Scala is quite similar to Java. One difference is that it is less picky with semicolons: they are optional at the end of the line. Also, Scala uses the "everything is an object" motto. All language constructs (primitive types & complex types, but also functions) are objects that can be passed around; this eases functional programming.
In [ ]:
// Which version of Scala?
scala.util.Properties.versionNumberString
Mutable and immutable values. Type inference
In [ ]:
// A mutable variable, defined with explicit type specification
var a: Int = 5
a = a + 1
println(a)
// Inmutable variables
val v1: Double = 6.2
val v2: String = "Hi!"
println( v1, v2)
// Same as before, but now we use type inference
val v1b = 6.2
val v2b = "Hi!"
println( v1b, v2b)
println( v1b.getClass, v2b.getClass )
In [ ]:
/* Define a function that takes an integer and returns an integer.
This one is a one-liner, otherwise we would use braces.
Also, we do not need a return statement since we are returning the last (and only) expression */
def fact(n: Int): Int = if (n == 0) 1 else n*fact(n-1)
In [ ]:
// Use the function
fact(10)
In [ ]:
// A function, with type specification
// (if the context was clear, we could use type inference)
val cube = (x : Int) => x*x*x
cube(7)
In [ ]:
// Same thing, but using explicit return type specification
val cube: Int => Double = x => x*x*x
cube(5)
In [ ]:
// If the function is more complex, we use a brace block
val cubeOrSquare = (x: Int) => { if( x < 10 )
x*x*x
else
x*x }
print( cubeOrSquare(7), cubeOrSquare(11) )
There is also a shorthand used in which we use the underscore (_
) as a placeholder for anonymous arguments, and we skip the argument list. See below
In [ ]:
// A function that takes another function and a value, and applies the function to the square of the value
def applySquared( func: Int => Int, value: Int) = func( value*value )
// Prepare the function we will pass
val minusOne = (x : Int) => x - 1
// This should compute x^2 - 1
print( applySquared( minusOne, 3 ) )
// We can also pass directly an anonymous function. This is x^2 + 2
applySquared( _ + 2, 6 )
In [ ]:
/* Define a class */
class Point( xc: Int, yc: Int ) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
}
override def toString(): String = "(" + x + ", " + y + ")";
}
/* Create an instance, and operate with it */
val p = new Point( 10, 11 )
p.move( 2, -1 )
println( p )
Scala predefines a good set of collections (similar to the ones existing in other programming languages) ready to be used. See Scala collections for documentation.
A list (ordered collection of items):
In [ ]:
var l = List( 1, 2, 3, 4, 5 )
In [ ]:
l.reverse
A set (unordered collection of items, with fast pertenence operations):
In [ ]:
var s = Set( "a", "b", "c", "d")
In [ ]:
s.contains( "c" )
In [ ]:
s & Set("a","c","f")
In [ ]:
val r = Range(1,10)
r
There is also a special syntax to define ranges using to
or until
In [ ]:
1 to 10
In [ ]:
// define a range with a fractional increment, and convert the result to Array
(1.0 until 10.0 by 0.5).toArray
In [ ]:
val numbers = List(1,2,3,4)
// We use here an anonymous function
numbers.map( x => 2 * x )
In [ ]:
// Same, but now with the shorthand using the underscore, which is interpreted as a reference to an anonymous argument
numbers.map( 2 * _ )
In [ ]:
// Another example
numbers.filter( _ <= 2 )
Another variant: the reduceLeft
function applies a binary operation (two parameters) successively, until all elements in the collection have been consumed:
In [ ]:
numbers.reduceLeft( (a, b) => a + b )
In [ ]:
// Again, using the underscore shorthand (each underscore refers to one of the two parameters)
numbers.reduceLeft( _ + _ )
In [ ]: