02a. Control Structures - RobertMakyla/scalaWiki GitHub Wiki

if else (interview)

if/else has a value, when it's used like java x>0 ? 1 : -1

val s = if (x > 0) 1 else -1   // it's equivalent to java's  x > 0 ? 1 : -1
                               // type Int, cause both branches give Int

Common supertypes:

if (x > 0) "+" else -1     - type Any, cause it's a common supertype
                             (-1 extends AnyVal, String extends AnyRef)

if (x > 0) "+" else null   - type String (Null extends AnyRef and its subtypes)
if (x > 0) 1 else null     - type Any (1 extends AnyVal, Null extends AnyRef)

if (x > 0) 1               - type AnyVal (both Int and Unit extends AnyVal)

if (x > 0) 1 else ()       - it's exactly the same

if (x > 0) null            - type Any (Unit extends AnyVal, Null extends AnyRef)

if (x > 0) null else null  - type Null = null

if (x > 0) "hi"            - type Any (Unit extends AnyVal, String extends AnyRef)

if (x > 0) "hi" else null  - type String (Null extends AnyRef and its subtypes, eg. String)

if (x > 0) 1 else throw new Exception("")  
                           - type Int
                           // cause throwingException has type Nothing (extends all types: Any/AnyRef/AnyVal)

if (x > 0) 1               - type AnyVal
                           // cause both Int and Unit extends AnyVal

() is of type Unit

Unit extends AnyVal (but not it's subtypes)

Null extends AnyRef with subtypes

Nothing extends Any/AnyRef/AnyVal with subtubes

subertype of T and Nothing is always T

but if/else has no value when it's used like java if/else

if (x > 0) s = 1 else s = -1

or I can always assign it:

val res = if (x > 0) s = 1 else s = -1     
            // res: Unit
           // but works only if s is a var
          // res has no value, but we save value to s variable

Scala combines the two if/else and (x>=0) ? x : -x constructs which are separate in java

In console, multiline if/else is an error (illegal start of definition 'else'). To fix it, need to add brackets { } :

if (x > 0) { 1
} else -1

In the code it's ok. No brackets { } are required.

##Blocks have value, of the last expressions

In java , block is a sequence of statements. In scala, block is a set of expressions which give value. The result is also an expression

{val a = 2 ; 9 ; val c = 3 ; math.pow(a,c)}             // Double = 8.0
{val a = 2 ; 9 ; val c = 3 ; val myPow = math.pow(a,c)} // Unit = ()

The last line has no sense cause myPow is not visible outside the block

##Assignments and () value - have Unit type

in Java, assignment has type of right side:

e.g. while ((line = br.readLine()) != null) {...}  )

in Scala:

var x = 1
var y = 1
x = y = 1

It gives error because y = 1 returns Unit = () and assigning Unit = () to anything other than Unit causes mismatch error.

The x = y = 1 is exactly like x = () which causes the same error (mismatch Int and Unit)

but the following is ok (no mismatch error):

var x: Unit = ()
var y = 1
x = y = 1

'for' loop is like enhanced java 'for' loop

for (i <- range) instruction

for( i <- 1 to 3)    println(i)       //  1 2 3
for( i <- 1 until 3) println(i)       //  1 2

var s = "hello" ; for( i <- 0 to s.length )    print(s(i))  // StringIndexOutOfBoundsException
var s = "hello" ; for( i <- 0 until s.length ) print(s(i))  // hello
for( i <- "hello" ) print (i)                               // hello

RichInt.to - returns Range (inclusive from both sides) RichInt.until - returns Range (inclusive from start, exclusive from end)

No need to declare the 'i' variable before. the 'for' loop declares it however the scope of the 'i' variable is only until the end of the loop

##BREAKING ('return') or VARIABLES - IT'S NOT FUNCTIONAL PROGRAMMING

Scala has no 'break' or 'continue' keyword. Scala has 'return' which looks ugly, or (since scala 2.8.0) I can:

import scala.util.control.Breaks._
var sum = 0
breakable {                  //breakable block, where I can use break
    for (i <- 0 to 1000) {
        sum += i
        if (sum >= 1000) break
    }
}

##Advanced loop features:

Multiple generators separated with ;

for (i <- 1 to 3; j <- 1 to 3) print((10 * i + j) + " ") 
// 11 12 13 21 22 23 31 32 33

Each generator may have an 'if' guard

for( i <- 0 until 10 if i < 5) 
print(i + " ")    // 0 1 2 3 4

for( i <- 1 to 3; j <- 1 to 3 if i != j) 
print((10 * i + j) + " ")   // 12 13 21 23 31 32

I can add any number of variable definitions (scope = inside the loop)

for (i <- 1 to 3 ; a=1 ; b=2 ; j <- 1 to 3; c=3 ; d=4) 
print((10 * i + j) + " ")   // 12 13 21 23 31 32

##"For Comprehension" collecting values from each operation

for (i <- 1 to 3) yield i     // returns collection of values: 
                             // Vector(1, 2, 3)

for (i <- 1 to 2; j <- "ab") yield "" + i + " " + j  

                            // Vector(1 a, 1 b, 2 a, 2 b)

Instead of using semicolons ';' I can have many generators, definitions in different lines but then I must replace for() with for{}:

for { i <- 1 to 3
      a = "any variable"
      j <- 1 to 3 
} print((10 * i + j) + " ") // 12 13 21 23 31 32

##Semicolons are mostly optional

It's required only if we want a set of statements in one line:

if(true) println("a"); println("b"); println("c")

if(true) { println("a"); println("b"); println("c") }  // the same

##The java 'void' type is 'Unit' in scala

##Input and Output

in:

val name = readLine("Your name: ")
val age = readInt()

out:

print("hi")
println(123)
printf("Hello, %s! You are %d years old.\n", "Robert", 29)

##Scala properties to read:

scala.util.Properties.userName

scala.util.Properties.versionString