/* CS:2820 Object Oriented Software Development Spring 2015 The University of Iowa Instructor: Cesare Tinelli */ /* Collection types: Arrays */ // creates an array with 5 elements and calls it a val a = new Array(5) // more typically, one specifies the element type as well; // the array elements start with a type-dependent default value val a = new Array[Double](5) a[1] // standard notation *not* used in Scala a(1) // Scala's notation for array access a(0) = 2.5 // array update a(5) // generates out of bound error // generates an Array[Int] of length 3 and elements 10,11, and 12; // element type Int is inferred Array(10, 11, 12) val a = Array(10, 11, 12) // 3 different ways to generate an Array[Long] // from Int initial values val a = Array[Long](10, 11, 12) // preferred one val a:Array[Long] = Array(10, 11, 12) val a = Array(10:Long, 11, 12) // note the tricky difference val a = Array[Long](10) // a is an Array[Long] with one element: 10 val b = new Array[Long](10) // n is an Array[Long] with 10 elements // array length a.length // multidimentional arrays are arrays of arrays val m = new Array[Array[Int]](10) val m = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12)) m(2)(1) // no special syntax for matrix access /* Scala examples seen in class */ /* Built-in control structures */ /* for loops */ // The for loop is an expression of type Unit // It can be seen as a mixfix operator with two arguments: // // for (_) _ // // The second argument (the "body") is any expression. // The first argument is a sequence of one or more *generators* // separated by ';' // // A generator is an expression of the form _ <- _ where the first // argument is a pattern and the second is an expression of a collection // type (Range, List, Array, ...) // below, the pattern 3 is matched against each element of the list. // each time there is a match, the body of for is evaluated for (3 <- List(1,3,4,3,5,3,6,3)) println("Hi") // as in the match and val constructs, patterns can contain variables for (i <- List(1,2,14,52,7,10)) println("high five") // any variables in the pattern have local scope within the for for (i <- List(1,2,14,52,7,10)) println("i = " + i) i // gives an error // patterns in a generator can be arbitrarily complex, depending // on the type of the collection val l = List((1,2), (1,4), (6,7), (3,6)) for ( (i, j) <- l ) println("i = " + i + ", j = " + j) for ( (i, _) <- l ) println(i) // ignores the second component of each pair for ( (1, j) <- l ) println(j) // only matches pairs starting with 1 // *any collection* type can be used in a generator for (i <- Array(1.2, 2.5, 4.5, 7.1)) println("i = " + i) for (i <- Set(1,2,4,5,7,10,4)) println("i = " + i) // even strings, which are seen as the collection of their characters for (i <- "abcd") println("i = " + i) // ranges are sequences of consecutive integers val r = Range(1,5) // contains values 1, 2, 3, 4 for (i <- r) println("i = " + i) // Expression 1 to 4 is the same as Range(1,5) for (i <- 1 to 4) println("i = " + i) // Putting more than one generator has the effect of nested for loops for (i <- 1 to 2; j <- 1 to 3) println("i = " + i + ", j = " + j) // the above for has the same effect as for (i <- 1 to 2) { for (j <- 1 to 3) println("i = " + i + ", j = " + j) } // and it can also be written as for { i <- 1 to 2 j <- 1 to 3 } println("i =" + i + ", j = " + j) // a generator can be optionally followed by a *filter* of the form: if b // where b is a Boolean expression. // the matched value is used if and only if b evaluates to true for (i <- List(1,9,2,4,5,7,10) if i > 4) println("i = " + i) val l = List((1,2), (1,4), (6,7), (3,6)) for ( (i,j) <- l if j == 2*i ) println((i,j)) for { c1 <- "hi" c2 <- "fifi" if c1 == c2 } println("character match found for letter " + c1) // BTW, matching filters can be used with the match construct too val l = List(2, 1, 3) l match { case x :: y :: t if (x > y) => y :: x :: t case _ => l } // the first case applies only if l has at least two elements *and* // its first element is greater than the second // this version of reverse scans the input list x using // a for loop instead of a recursive call, // each element of x is inserted into an initialy empty list; // a mutable variable is necessary to store the growing reversed list // def reverse(x:List[Int]):List[Int] = { var l = List[Int]() for (h <- x) l = h :: l l }