| LevSelector.com |
Scala Programming Language
| On This Page | More | Other Pages |
|
- intro |
- |
- |
Intro ------------------------------
Scala programs run on JVM (Java Virtual Machine),
|
![]() Martin Odersky, creator of Scala |
It was successfully used to develop Apache Spark - architecture for fast distributed data processing.
Hello, world ------------------------------
object MyApp extends App { var a = 0; for( a <- 1 to 10){ /* comment */ println( "Value of a: " + a ); // comment } } |
Now you can compile and run:
scalac test.scala
scala MyApp
Note in the above example:
If you run scala without file name - it enters interactive mode:
> scala
Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_65).
Type in expressions to have them evaluated.
Type :help for more information.
scala> var a=1
a: Int = 1
scala> for(a <- 1 to 3) println("help" + a)
help1
help2
help3
scala> :quit |
In interactive mode scala has many convenient commands which start with ":", for example: :help [command] print this summary or command-specific help :history [num] show the history (optional num is commands to show) :load <path> interpret lines in a file :paste [-raw] [path] enter paste mode or paste a file :power enable power user mode :quit exit the interpreter :save <path> save replayable session to a file :sh <command line> run a shell command (result is implicitly => List[String]) etc. etc. - use :help to see the whole list Note: In interactive mode you can use auto-expansion help by hitting <TAB> key |
// Two ways to run a scala script in file test.scala:
// file test.scala:
var word = "World"
println("Hello " + word)
// running from unix prompt:
> scala test.scala
// running from scala prompt
scala>:load test.scala |
Similarly you can run scala from spark prompt.
You can also use an IDE with scala plugin, for example:
arithmetics ------------------------------
arithmetics
scala> print(1);print(2) |
// removing decimals
ff = 5.9
ii = ff.toInt // 5
ff = -5.9
ii = ff.toInt // -5
// rounding
ff = 5.9
ii = ff.round // 6, Long
ii = ff.round.toInt // 6, Int
// round, ceil, floor
// rounding to cents
ff = 12.34567
var ff2 = ((ff*100.0).round)/100.0 // 12.35
ff2 = ((ff*100.0).round)/100.0 // 12.35
|
// provide type while declaring the variable: |
// checking type
def getInteger(obj: Any) = obj match {
case n: Number => n.longValue
case b: Boolean => if(b) 1L else 0L
case s: String if s.length != 0 && s != "null" => s.toLong
case _ => null
}
// http://stackoverflow.com/questions/19386964/i-want-to-get-the-type-of-a-variable-at-runtime
// testing if two variables point to the same object (or equal for primitive types)
def refEquals(a: Any, b: Any) = a match {
case x: Boolean if b.isInstanceOf[Boolean] => x == b
case x: Byte if b.isInstanceOf[Byte] => x == b
case x: Short if b.isInstanceOf[Short] => x == b
case x: Char if b.isInstanceOf[Char] => x == b
case x: Int if b.isInstanceOf[Int] => x == b
case x: Float if b.isInstanceOf[Float] => x == b
case x: Double if b.isInstanceOf[Double] => x == b
case x: Long if b.isInstanceOf[Long] => x == b
case _ => a.asInstanceOf[AnyRef] eq b.asInstanceOf[AnyRef]
}
// http://stackoverflow.com/questions/8087066/method-to-check-reference-equality-for-any-type
// http://www.slideshare.net/knoldus/object-equality-inscala
// http://www.artima.com/pins1ed/object-equality.html - very good article discussing how to define custom
equals() method to avoid problems when placing objects into collections, subclassing, etc. |
Scala doesn't have primitive types, all types are objects.
It has same data types as Java:
Byte, Short, Int, Long, Float, Double, Char, String, Boolean
also:
// char,string, multiline-string:
'\n' - char
"\n" - string
""" multiline
string""" |
Access Modifiers - private, protected, public (default is public)
// if/else:
if( x == 10 ){
println("10");
}else if( x == 20 ){
println("Value of X is 20");
}else{
println("This is else statement");
}
|
// loops: |
functions ------------------------------
functions
// function definition (parameters, return_type, and return_expression are optional):
def myFunc ([parameters]) : [return_type] = {
statements
return [expr]
}
// function working with specific types
def addInt( a:Int, b:Int ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
// if no return statement - the result of last executed statement is returned
def addInt( a:Int, b:Int ) : Int = {
a + b
}
// function working with different types
// http://stackoverflow.com/questions/4056452/how-do-i-implement-a-generic-mathematical-function-in-scala
// http://stackoverflow.com/questions/485896/how-does-one-write-the-pythagoras-theorem-in-scala
def addAny[T](a:T, b:T)(implicit num: Numeric[T]): T = {
import num._
var sum: T = a
sum = a + b
return sum
}
// void function (type "Unit")
def printMe( ) : Unit = {
println("Hello, Scala!")
} |
// anonymous functions and closures:
var factor = 4
val myMult = (i:Int) => i * factor
println("myMult(2) value = " + myMult(2)) // 8
println("myMult(3) value = " + myMult(3)) // 12
|
strings ------------------------------
More about strings
// strings: |
Array ------------------------------
Array - fixed nubmer of elements (variables) of the same type.
// Array:
var aa = Array(11,22,33) // Array[String]
var aa = Array("mama", "papa123", null) // Array[String]
var aa = new Array[String](3) // Array[String] = Array(null, null, null)
aa(0) = "mama"
aa(1) = "papa123"
aa(2) = "dada4"
for (ii <- 0 to (aa.length - 1)) println(aa(ii))
// concatenate arrays
var aa = Array(1,2,3)
var bb = Array(4,5)
var cc = concat(aa,bb) // Array(1, 2, 3, 4, 5)
// multi-dimensional array = array of arrays
import Array._
var mm = ofDim[Int](3,3)
for (ii <- 0 to 2) {
for ( jj <- 0 to 2) {
mm(ii)(jj) = ii + jj;
}
}
// using range() function
import Array._
var aa = range(0,5) // Array[Int] = Array(0, 1, 2, 3, 4)
var aa = range(0,5,2) // Array[Int] = Array(0, 2, 4)
var aa = range(5,0,-1) // Array[Int] = Array(5, 4, 3, 2, 1)
// creating array of objects using apply():
import Array._
var aa = apply(1,2,3)
// copy elements from src into dest array:
// copy(src, srcPos, dest, destPos, length)
import Array._
var aa = range(0,3) // Array(0, 1, 2)
var bb = range(10,15) // Array(10, 11, 12, 13, 14)
copy(aa, 1, bb, 2, 2) // Array(10, 11, 1, 2, 14)
// create an empty array of a given type
var aa = Array.empty[Float] // Array[Float] = Array()
// apply a function repeatedly - return Array of progressive results
// Array.iterate(start_val, num_steps)(func)
Array.iterate(10, 3)(_ + 2) // Array(10, 12, 14)
Array.iterate(1, 5)(2 * _) // Array(1, 2, 4, 8, 16)
Array.iterate(1, 5)(n => 2 * n) // Array(1, 2, 4, 8, 16)
// fill array with some computed values
Array.fill(3){ "%.3f" format (math.random) } // Array[String] = Array(0.722, 0.079, 0.421)
// Note - you can use Array.fill(M,N)(func) to fill in 2-dimensional array
// fill Array applying simple function to indexes
Array.tabulate(3)(_ + 3.1) // Array(3.1, 4.1, 5.1)
Array.tabulate(4)(_*2) // Array(0, 2, 4, 6)
Array.tabulate(2,3)(_ + 3*_) // Array(Array(0, 3, 6), Array(1, 4, 7))
|
collections - List ------------------------------
Collections - List
// List
List(1,2,3,4) // immutable linked list
List() // empty list
Nil // empty list
val zeros = List.fill(10)(0.0) // create list of 10 elements - and fill with 0.0
val squares = List.tabulate(6)(n => n * n) // List(0, 1, 4, 9, 16, 25)
List("AA", "BB", "CC")
var aa = "AA" :: "BB" :: "CC" :: Nil // List("AA", "BB", "CC")
aa(2) // third element of the list
var bb = List("a", "b")
var cc = List("c", "d")
bb ++ cc // concatenate two lists together
bb ::: cc // same
Lisc.concat(bb,cc) // same
// count elements whic satisfy a criterium |
collections - Set ------------------------------
Collections - Set
// Set - elements of the same type, no duplicates, no guaranteed order
var nums1 = Set(2,3,4,5) // immutable Set (no duplicates)
import scala.collection.mutable.Set // switch to mutable sets
var nums2 = Set(2,3,4,5) // mutable set
nums1.head // get one (first) element
nums1.tail // get a Set of all other elements
nums1.last // last element
nums1.init // get a Set of all elements except last
// Empty set of integer type
var ss : Set[Int] = Set()
ss.isEmpty // true
// combining two sets:
s1 ++ s2
s1.++(s2)
s1 | s2
// find max or min:
s1.max
s1.min
// find intersection of two sets
s1 & s2
s1.&(s2)
s1.intersect(s2)
// find differenece between sets
s2 &~ s1 // same as s2 diff s1
s1 &~ s2 // same as s1 diff s2
// check is one set is a subset of another
s2 subsetOf s1
// add or remove an element (creates a new set)
s1 + 55
s1 - 2
// check if element is in the Set:
s1.contains(2)
s1.apply(1)
s1.exists(_ > 0)
// length of the set
s1.size
// count number of elements satisfying some criteria
s1.count(_>=1)
// copy elements to array
s1.copyToArray(arr, arr_start, len)
// check if two sets are the same
var s1 = Set(1,2,3)
var s2 = Set(3,2,1)
s1 == s2 // true (actually compares values)
s1 eq s2 // false (compares if ref. point to the same object)
// more methods
drop
dropRight
dropWhile
filter(_ > 0)
find(_ > 0) // returns first element which satisfies
forall(_ > 0) // tests for all elements
foreach()
iterator
map
mkString // all elements as a string
mkString("|")
toString
toSeq
toList
toMap
toBuffer
toArray
take(2) / get 2 elements
product // product of all elements
sum // sum of all elements
splitAt(5) // splits a set into 2 (5 and N-5 elements)
take(5) // first 5 elements
takeRight(5) // last 5 elements
|
collections - Map ------------------------------
Collections - Map
// Map (dictionary, hash) - by default immutable (can add elements, but can not remove them)
import scala.collection.mutable.Map // switch to mutable Maps
var xx = Map("k1" -> 1, "k2" -> 2, "k3" -> 3)
xx.keys |
collections - Tuple ------------------------------
Collections - Tuple
// Tuple - can hold objects of different types, but not more than 22 of them
val xx = (10, "Hello", 5.5) // Tuple3[Int, String, Double]
// accessing elements of a tuple
xx._1
xx._2
etc.
// looping through a tuple:
xx.productIterator.foreach{ i =>println("Value = " + i )}
Value = 10
Value = Hello
Value = 5.5
// string representation
xx.toString // "(10,Hello,5.5)" |
collections - Option ------------------------------
Collections - Option
// Option - container for zero or one element of a given type val x:Option[Int] = Some(5) // An Option[T] can be either Some[T] or None object, which represents a missing value. // getOrElse or isEmpty methods: a.getOrElse(0) // will return 0 instead of None isEmpty // true or false // option methods: get // returns the value (or None) isEmpty exists(_ > 2) filter(_ > 2) filterNot(_ > 2) flatMap foreach getOrElse isDefined iterator map orElse orNull |
Iterator ------------------------------
Iterator
// Iterator - not a collection, but rather a way to access the elements of a collection one by one
val it = Iterator("a", "number", "of", "words")
while (it.hasNext){
println(it.next())
}
// methods
it.max
it.min
it.size
it.length
it1.++(it2)
addString(sb)
addString(sb,"|")
buffered
contains
copyToArray(arr, arr_start, len)
count(_ > 2)
drop(5)
dropWhile(_ > 2)
duplicate
exists
filter
filterNot
find
flatMap
forall
foreach
hasDefiniteSize
indexOf
indexWhere
isEmpty
isTraversableAgain
length
map
max
min
mkString
mkString("|")
nonEmpty
padTo
patch
product
sameElements
seq
size
slice
sum
take
toArray
toBuffer
toIterable
toIterator
toList
toMap
toSeq
toString()
zip |
Classes ------------------------------
Classes
// classes and objects:
import java.io._
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
class Location(override val xc: Int, override val yc: Int,
val zc :Int) extends Point(xc, yc){
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("Point x location : " + x);
println ("Point y location : " + y);
println ("Point z location : " + z);
}
}
object Test {
def main(args: Array[String]) {
val pt = new Location(10, 20, 30); // created an object
pt.move(10, 11, 12); // invoke a method
}
}
|
// Singleton objects:
// In Scala we cannot have static members.
// Instead, Scala has singleton objects.
// Just put the constructor code in the body of the object definition:
object MyObject {
println("Hello") // This will print hello the first time
// the Foo object is accessed (and only
// that once).
} |
// A trait is similar to interface in Java.
// A trait may contain method and field definitions
// A class can extend multiple traits
// A trait definition looks like class definition (but using word "trait" instead of "class",
// and a trait can not have constructor parameters)
// note - if you expect inheriting from it in Java code,
// or expect outside groups to inherit from it,
// or need performance - it is better to use classes than traits.
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
class Point(xc: Int, yc: Int) extends Equal {
var x: Int = xc
var y: Int = yc
def isEqual(obj: Any) =
obj.isInstanceOf[Point] &&
obj.asInstanceOf[Point].x == x
} |
--
Matching ------------------------------
xxxxxxx
// match:
def matchTest(x: Any): String = {
var aa = x match {
case 1 => "one"
case "two" => "two2"
case y: Int => "scala.Int" // testing type
case _ => "many" // default
}
return " " + x + " " + aa
}
// match using "case" Classes:
val p1 = new Person("name1", 25)
val p2 = new Person("name2", 35)
for (person <- List(p1,p2)) {
person match {
case Person("name1", 25) => println("p1")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
// prepending the "case" before a class name does the following:
// compiler automatically converts the constructor arguments
// into immutable fields, it automatically implements equals,
// hashCode, and toString methods to the class. |
// regex matching:
// when defining regex, use raw strings (""")
val ss = """\.+((xyz)|(abc))""" // String = \.+((xyz)|(abc))
// adding .r at the end of the script creates a Regex object
import scala.util.matching.Regex
val ss = """\.+((xyz)|(abc))""".r // scala.util.matching.Regex = \.+((xyz)|(abc))
// use Regex constructor explicitly
import scala.util.matching._
val Name = new Regex("""(\w+)\s+(\w+)""") // scala.util.matching.Regex = (\w+)\s+(\w+)
// use .matches() method
"mama papa dada".matches("(?i).*\\sPAPA\\s.*") // true
// ways to match / replace:
// regex findFirstIn mystr
// regex replaceFirstIn(mystr, "mama")
// regex findAllIn mystr - returns an iterator over the matches.
// regex replaceAllIn(mystr, "mama")
// Example:
"l|he".r findAllIn "hello xyz" foreach {println _}
he
l
l
("(h)(e)|(l)".r findAllIn "hello xyz").matchData foreach { m => println(m.start, m.end, m.before, m.after, m.source)}
(0,2,,llo xyz,hello xyz)
(2,3,he,lo xyz,hello xyz)
(3,4,hel,o xyz,hello xyz)
val date = "11/01/2010"
val DateRegex = """(\d\d)/(\d\d)/(\d\d\d\d)""".r
Date: scala.util.matching.Regex = (\d\d)/(\d\d)/(\d\d\d\d)
val Date(day, month, year) = date
println(day) // 11
println(month) // 01
println(year) // 2010
Some examples were taken from these posts:
// http://daily-scala.blogspot.com/2010/01/regular-expression-1-basics-and.html
// http://daily-scala.blogspot.com/2010/01/regular-expression-2-rest-regex-class.html
// http://daily-scala.blogspot.com/2010/01/regular-expression-3-regex-matching.html |
exceptions ------------------------------
exceptions
// exceptions:
// try{}catch{}finaly{} blocks like in Java,
// but the "catch" block uses matching to identify and handle the exceptions.
// You can also "throw" exceptions (like in java)
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Test {
def main(args: Array[String]) {
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => {
println("Missing file exception")
}
case ex: IOException => {
println("IO Exception")
}
} finally {
println("Exiting finally...")
}
}
} |
misc ------------------------------
misc
// exctractor: // extractor is an object with method unapply() to match // a value and take it apart. |
// reading directory:
import java.io.File
var allFiles = new File(myDirectoryPath).listFiles
var textFiles = allFiles.filter(_.getName.endsWith(".txt"))
var text_fnames = textFiles.map(_.getName) |
// reading lines from file: import scala.io.Source val lines = Source.fromFile(someFileName).getLines() var mylines = lines.toList |
// Currying: |
// scala.concurrent // Explore Scala concurrency // - http://www.ibm.com/developerworks/java/library/j-scala02049/index.html // Dive deeper into Scala concurrency // - http://www.ibm.com/developerworks/java/library/j-scala04109/index.html // (actor based message passing model) |
// processing command line arguments:
object Lev1 { |
// SBT (Simple Build Tool): - an open source build tool for Scala and Java projects. - build descriptions written in Scala using a DSL - integrated Scala interpreter for rapid debugging |
// running system commands |
// speed considerations - loops or recursion // http://stackoverflow.com/questions/15138624/scala-recursion-vs-loop-performance-and-runtime-considerations // while loops and tail recursion are the same speed and fast // regular recursion and for-loops are slower. // (Regular recursion may not be slower if the JVM optimization makes it equivalent) |
// write to file:
import java.io._
val writer = new PrintWriter(new File("test.txt" ))
writer.write("Hello Scala")
writer.close()
// read from file
import scala.io.Source
Source.fromFile("test.txt" ).foreach{ print }
// receive line from console screen
print("Enter line : " )
val line = Console.readLine
println("You entered: " + line) |
// xxxxx: |
// xxxxx: |