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