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: |