Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this presentation? Why not share!

Like this? Share it with your network

Share

Advanced Scala

  • 1,007 views
Uploaded on

This presentation was part of a seminar in a masters course. It covers 3 chapters of Martin Odersky's Book "Programming in Scala" (Packages and Imports, Assertions and Unit testing, Case Classes......

This presentation was part of a seminar in a masters course. It covers 3 chapters of Martin Odersky's Book "Programming in Scala" (Packages and Imports, Assertions and Unit testing, Case Classes and Pattern Matching).

More in: Technology , Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,007
On Slideshare
1,007
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
33
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Masterseminar Scala Fabian Becker FH Giessen-Friedberg 15. November 2010
  • 2. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Content 1 Packages & Imports 2 Assertions and Unit Testing 3 Case Classes and Pattern Matching
  • 3. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Packages Packages Important to minimize coupling Scala code resides in Java global hierarchy of packages Per default code is in the unnamed package There are two ways to place code inside packages Listing 1.1 package database.mysql class Query
  • 4. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Packages Listing 1.2 package database { package mysql { class Query } } Listing 1.3 package database.mysql { class Query }
  • 5. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Packages Packages Packages in Scala truly nest In Java packages are in a hierarchy they don’t nest Naming a package in Java you always start at the root
  • 6. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Packages Listing 1.4: Accessing packages package game { package ui { class Player } package engine { class Main { // Java: new game.ui.Player() val player = new ui.Player } } }
  • 7. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Packages Listing 1.5: More complex package ui { class Player } // In ui.scala package game { // In game.scala package ui { class Player } package engine { package ui { class Player } class Main { val player = new ui.Player val player2 = new game.ui.Player val player3 = new _root_.ui.Player } } }
  • 8. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Imports Importing packages Importing packages allows to directly access members in that package Scala imports are similar to the imports from Java Imports can appear anywhere
  • 9. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Imports Listing 1.6.1: Defining Enemies package game abstract class Enemy( val name: String, var lvl: Int ) object Enemies { object Dwarf extends Enemy("Gimli", 10) object Orc extends Enemy("Bwarg", 5) object Necromancer extends Enemy("Destructor", 99) val col = List(Dwarf, Orc, Necromancer) }
  • 10. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Imports Listing 1.6.2: Importing Enemies // Simple import for Enemy import game.Enemy // Import all members of game import game._ // Import all members of Enemies import game.Enemies._
  • 11. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Imports Listing 1.7: Import in a function def showEnemy(enemy: Enemy) { import enemy._ println("Enemy - Name:"+name+" Level:"+lvl) } Imports Imports can appear in functions They import all members of a object
  • 12. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Selective Imports Listing 1.8: Selective Imports // Only import Dwarf and Orc import game.Enemies.{Dwarf, Orc} // Renaming an import import game.Enemies.{Necromancer => Necro} // Rename one, import the rest import game.Enemies.{Orc => O, _} // Exclude an import import game.Enemies.{Orc => _, _}
  • 13. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Selective Imports Selective Imports Import: import game.Enemies.{Orc} ⇔ game.Enemies.Orc Rename: originalname ⇒ new name Hide Packages: original − name ⇒ Catch All: importgame.Enemies.{ } ⇔ game.Enemies.
  • 14. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Implicit imports Listing 1.9: Implicit imports import java.lang._ // everything in the java.lang package import scala._ // everything in the scala package import Predef._ // everything in the Predef object Implicit imports Packages imported implicitly by Scala scala. overshadows java.lang. scala.StringBuilder ⇒ java.lang.StringBuilder
  • 15. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Access modifiers Listing 1.10: Private modifiers class Outer { class Inner { private def f() { println("f") } class MostInner { f(); // OK } } (new Inner).f() // fails } Private Scala: private members are only accessible inside the class or object that contain their definition Java allows outer classes to access private members of their inner classes
  • 16. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Access modifiers Protected Java: protected members are accessible within the same package Scala: Only from the object they are defined in and their subclasses Public There is no explicit modifier for public All members not labeled private or protected are public Accessable from anywhere
  • 17. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Access modifiers Scope of protection Scala allows to control access to a level X private[X] and protected[X] allow access up to X Listing 1.11: Example package game { package ui { private[game] class Player { private[this] var hp = 42 protected[ui] def getHP() { hp } } } }
  • 18. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Assertions and Unit Testing Testing Code Assertions for run-time checking Unit testing for development testing of small units
  • 19. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Assertions Listing 2.1: Assert def add1(x: Int) : Int = { val z = x + 1 assert(z > x) return z } println(add1(41)) Assertion methods Method assert predefined in Predef assert(condition) assert(condition, explanations) If the condition doesn’t hold, an AssertionError is thrown
  • 20. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Assertions Listing 1.13: Ensuring def lvlUp(e: Enemy): Enemy = { if(e.lvl < 100) { e.lvl = e.lvl + 1 } ensuring(e.lvl < 100) e } Ensuring Method assert predefined in Predef assert(condition) assert(condition, explanations) If the condition doesn’t hold, an AssertionError is thrown
  • 21. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing ScalaTest org.scalatest.Suite (http://www.scalatest.org/) Can be executed on the Scala console: (new HitchhikerSuite).execute() Listing 2.3: Simple testcase import org.scalatest.Suite class HitchhikerSuite extends Suite { def testAnswerToLife() { val answer = 42 assert(answer == 42) } }
  • 22. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing ScalaTest with Fun ScalaTest allows different styles of testing FunSuite is a trait that overrides execute and allows to define tests as function values Naming the tests is easier (you can use Strings) Listing 2.4: FunSuite import org.scalatest.FunSuite class HitchhikerSuite extends FunSuie { test("The answer to life should be 42") { val answer = 42 assert(answer == 42) } }
  • 23. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing ScalaTest - Informative testing A normal assertion produces long error messages but do not show why the match failed ScalaTest defines the === operator for assert(), shows the values Alternative: expect(value) { block } Listing 2.5: Informative testing assert(answer === 42) // or expect(42) { answer }
  • 24. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing ScalaTest - Catching Exceptions Testing for Exceptions can be done with intercept() Listing 2.6: Intercept s = "hi" intercept[IndexOutOfBoundsException] { s.charAt(-1) }
  • 25. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing JUnit Most popular test framework for Java Can easily be used from Scala Does not natively support Scala’s assertion syntax Listing 2.7: JUnit Testcase import junit.framework.TestCase import junit.framework.Assert.assertEquals import junit.framework.Assert.fail class MyTestCase extends TestCase { def testAnswer() { val answer = 42 assertEquals(42, answer) } }
  • 26. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing JUnit + Scala ScalaTest defines JUnit4Suite (requires JUnit 4 of course) JUnit4Suite extends TestCase Listing 2.8: Using Scala syntax in JUnit import org.scalatest.junit.JUnit4Suite class AnswerSuite extends JUnit4Suite { def testAnswerToLife() { var answer = 42 assert(answer === 42) } }
  • 27. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing TestNG TestNG framework inspired by JUnit/nUnit Uses annotations Listing 2.9: TestNG import org.testng.annotations.Test import org.testng.Assert.assertEquals class AnswerTests { @Test def verifyAnswerToLife() { val answer = 42 assertEquals(answer, 42) } }
  • 28. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing TestNG + Scala ScalaTest defines trait TestNGSuite TestNGWrapperSuite enables TestNG to test Scala while the tests are written in Java Listing 2.10: TestNG + Scala import org.scalatest.testng.TestNGSuite import org.testng.annotations.Test class AnswerSuite extends TestNGSuite { @Test def verifyAnswerToLife() { val answer = 42 expect(42) { answer } assert(answer === 42) } }
  • 29. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing Listing 2.11: TestNG + Scala import org.scalatest.Spec class AnswerSpec extends Spec { "The Answer" -- { "should be an integer" - { val answer = 42 assert(answer.isInstanceOf[Int] == true) } "should be 42" - { val answer = 42 assert(answer === 42) } } }
  • 30. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Unit testing Tests as specification Behavior-driven-development (BDD) lays emphasis on human-readable testing ScalaTest includes a trait Spec Spec contains describers and specifiers Each specifier will be run as a seperate ScalaTest Output (new AnswerSpec).execute() The answer - should be an integer - should be 42
  • 31. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Case Classes and Pattern Matching Tests as specification Case Classes Pattern Matching
  • 32. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Case classes Listing 3.1: Definitions abstract class Expr case class Var(name: String) extends Expr case class Number(num: Double) extends Expr case class UnOp(operator: String, arg: Expr) extends Expr case class BinOp(operator: String,left: Expr, right: Expr) extends Expr The case modifier Example from the book The case modifier adds syntactic conveniences Factory method: val v = Val(”x”)
  • 33. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Case classes Listing 3.2: Nesting val op = BinOp("+", Number(42), Var("x")) The case modifier Allows to ommit the new All constructor parameters implicitly get a val prefix toString, equals, hashCode are automagically added
  • 34. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Listing 3.3: Matching def simplifyTop(expr: Expr): Expr = expr match { case UnOp("-",UnOp("-",e)) => e // Double negation case BinOp("+", e, Number(0)) => e // Adding zero case BinOp("*", e, Number(1)) => e // Multiplying by one case _ => expr } Matching Similar to Javas switch Syntax: selector match {alternatives} match is an expression and results in a value
  • 35. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Patterns e, variable pattern , wildcard pattern, drops the value UnOp(“-“, e), constructor pattern, matches values of type UnOp with - as first param. If no pattern matches a MatchError is thrown. Listing 3.4: Matching expr match { case BinOp(_, _, _) => println(expr +"is a binary operation") case _ => println("It’s something else") }
  • 36. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Constant patterns Any literal (String, Boolean, Integer) can be used as a pattern Literals match themselves Listing 3.5: Constant patterns def inspect(x: Any) = x match { case 12 => "twelve" case Nil => "nothing" case false => "negative" case _ => "Cant’t say" }
  • 37. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Variable patterns Variable pattern matches like a wildcard, but the result gets assigned to the variable Listing 3.6: Variable patterns expr match { case 12 => "Not right" case number => "This is a number " + number }
  • 38. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching How does Scala tell them apart? Scala uses a lexical rule to differ between variable and constant patterns Lowercase identifiers are treated as variable Uppercase identifiers are assumed to be a constant Exception to the rule? true and false
  • 39. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Constructor patterns Check against a constructor and it’s parameters Object gets inspected Contents of the object are checked aswell Listing 3.7: Constructor pattern expr match { case BinOp("-", m, Number(12)) => println(m + " - 12") case _ => }
  • 40. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Sequence patterns Match against sequence types like List, Array, ... Allows to specify the number of elements in the pattern ⇔ Wildcard, * ⇔ 0..n elements Listing 3.8: Sequence pattern with fixed length expr match { case List(n, _, _) => println("Top-Element: " + n) case List(n, _*) => println("Top-Element: " + n) case _ => }
  • 41. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Tuple patterns A pattern like (x, y) matches a 2-tuple Listing 3.9: Tuple pattern expr match { case (x, y) => println("Matched a 2-tuple") case _ => }
  • 42. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Typed patterns Alternative for type checks and type casts Type check: expr.instanceOf[String] Type cast: expr.asInstanceOf[String] Listing 3.10: Typed pattern def getSize(e: Any) = e match { case s: String => s.length case m: Map[_,_] => m.size case _ => -1 }
  • 43. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Type erasure Matching a Map with special element types doesn’t work! Scala/Java use the erasure model for generics No information about type arguments is maintained at run-time Arrays are an exception, they are handled differently Listing 3.11: Type erasure - Matches all Maps! expr match { case m: Map[Int, String] => println("String-Int Map") case _ => }
  • 44. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Variable binding Perform the normal match but bind the match to a variable The @ sign binds a variable to a match Listing 3.12: Binding a variable to a match expr match { case UnOp("abs", e @ UnOp("abs", _)) => e case _ => }
  • 45. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Pattern guards Sometimes a match can have pre-conditions The conditions are “guarding“ the match Listing 3.13: Match with pre-condition expr match { case BinOp("/", _, y) if y == 0 => println("Nominator can’t be 0") case _ => }
  • 46. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Pattern overlaps Patterns are tried in the order they’re written Changing the order of cases can change behaviour Listing 3.14: Simple pattern overlap expr match { case BinOp("+", e, Number(10)) => println("BinOp + 10") case BinOp("-", e, Number(10)) => println("BinOp - 10") case BinOp(op, e, Number(10)) => println("BinOp "+op+" 10") case _ => expr }
  • 47. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Sealed classes When you match using patterns, how do you make sure you matched everything? sealed classes allow the compiler to know all possible cases A sealed class can only have subclasses in the same file The compiler can then generate warnings (match not exhaustive) Listing 3.15: Sealed class sealed abstract class Expr case class Var(name: String) extends Expr case class Number(num: Double) extends Expr
  • 48. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Sealed classes If you leave out an option a warning is thrown: “warning: match is not exhaustive! missing combination Type“ Listing 3.16: Match on a sealed class expr match { case Var(x) => "Variable " + x }
  • 49. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Sealed classes Warning can be avoided by doing a wildcard match Suppressed using an annotation (will be covered in Chapter 25) Usefulness? Why make the class sealed in the first place? Listing 3.17: Match on a sealed class (expr: @unchecked) match { case Var(_) => "a variable" }
  • 50. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching The Option type Standard type for optional values Can be Some(x) or None Is returned by HashMap, Map, .. None is the Scala way of returning null Listing 3.18: Unpacking an option val map = Map(1 -> "a", 2 -> "b", 3 -> "c") (map get 1) match { case Some(s) => println(s) case None => println("Not there") }
  • 51. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Patterns in other places Patterns can be used almost anywhere Listing 3.19: Other uses of patterns val (a, b) = (1, 2) for((num, letter) <- Map(1->"a", 2->"b")) println("Num:"+num+" Letter:"+letter)
  • 52. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Case sequences as partial functions Case sequences can be used partial functions Partial functions throw a RuntimeException if they are applied against a value they don’t support Compiler can throw warnings Listing 3.20: Case sequence as partial function val myMatch: Option[Int] => String = { case Some(x) => "Value: " + x case None => "Nothing there" } myMatch(Some(12)) // => Value: 12
  • 53. Packages & Imports Assertions and Unit Testing Case Classes and Pattern Matching Pattern matching Case sequences as partial functions By telling the compiler that you use a partial function you can check whether it’s possible to apply a value Listing 3.21: val listMatch: PartialFunction[List[Int], Int] = { case x :: y :: _ => y } // Can we apply the List? listMatch.isDefinedAt(List(1,2,3)) // => true