A program expresses a computation. For instance: What is the result of adding one to one?
1 + 1
Evaluating the program “1+1” returns the value “2”.
In the program 1+1 we say:
How many letters are in the text “Hello, world1!”?
"Hello, world1!".length
.
or dot notation), length to itConsider the following scala program:
"length".length
1 > 0 true greater than (a comparison operation)
1 == 0 false equals to (another comparision operation)
1.max(0) 1 max operation returns the greater value between the left and right argument
-5.abs 5 absolute value operation
"Hello, " + "world!" "Hello, world!" concatentation operation
"#" * 3 "###" times operation
"Alice".toUpperCase "ALICE" to upper case operation
true && true true logical and operation with infix notation
true.&&(true) true logical and operator with dot notatation
Large expressions are hard to read and write. We can give names to fragments of expressions and then refer to them by using these names.
val facade = 5 * 3
val door = 1 * 2
var areaToPaint = facade - door
In Scala names are introduced with the val keyword.
Let’s now define these terms slightly more formally
42
, the character 'B'
, and the text "Hello, World"
, or the function (a:String, b:String) => a + a
(x:Int) => x
val x = 1
var a = 1
var x:Int = 1
Here Int is the type. You can use the scala repl to entery these commands val x: Int = 42
println(x)
// x = 2 throws a reassignment to val error. vals are immutable
val x2 = 42
// specifying the type is optional. The compiler figures out the type from type inference
// val x3: String = 42 won't
//some types
val aBoolean: Boolean = true
val aChar: Char = 'x'
val anInt: Int = x
val aShort: Short = 1; // Short.MaxValue is the biggest short
val aLong: Long = 1000L // use the L to tell the compiler you want a Long not an Int
val aDouble: Double = 2.0
val aFloat: Float = 2.0f // use the f to tell the compiler you want a Float not a Double
// variables
var aVariable: Int = 5
aVariable = 6 // here we are able to reassign data to a variable via a side-effect
An Expression is any bit of code that yields a result. You can also say that an expression evaluates to
a result or results in
a value. Compare this to a an Instruction or a Statement
val x = 1 + 2 // 1 + 2 is an Expression. This expression is evaluated to the value 3 and has type Int
// It is then assigned to the val x
println(x)
println( 2 + 3 * 4)
// Some math operators + - * / & | ^ << >> >>> (right shift with zero extension)
println( 1 == x)
// Some boolean operators == != > >= < <=
println(!(1 == x))
// ! is the unary negation operator
var aVariable = 2
aVariable += 3 // also works with -=, *= /= ... side effects on variables
// Instructions (DO something ) VS Expressions (VALUE and type)
// Consider the IF expression
val aCondition = true
val aConditionedValue = if(aCondition) 5 else 3
println("aConditionedValue: " + aConditionedValue)
// Scala while has loops but often we don't need them
var i = 0
while(i < 10) {
println(i)
i += 1
}
println("fancy: " +( 1 to 10).mkString(","))
// A while loops *is* an expression. But it is an expression of type Unit, and there
// action is done as a side effect
// side effects: println(), whiles, reassigning to a var
// code blocks
val aCodeBlock = {
val y = 2
val z = y + 1
if(z >2) "hello" else "goodbye"
}
// everything inside the { } is a code block. It is also an expression, it value is the value of
// the final expression in the code block.
A Function can be invoked with a list of arguments to produce a result. A function has a parameter list, a body, and a result type. Functions that are members of a class, trait or singleton object, are called methods. Functions defined inside other functions are called local functions. Functions with the result type of Unit
are called procedures. Anonymous functions in source code are called function literals. At run time, function literals are instantiated into objects called function values