======= Scala @ PP =======
===== "Meta ideas" =====
Test-driven development
===== 1. Installation =====
===== 2. Syntax =====
2.1. Writing functions
2.2. Function evaluation (order of parameters in function call matters !)
- using the ''=>'' to delay evaluation
2.3. Conditionals
- '' def f(x : Int) = if (x >= 0) x else -x''
- boolean expressions (''true'', ''false'', ''!b'', ''&&'', ''||'')
- the "by value" definition using ''val''
- example using def and val against a loop
Newton square root estimation
* Blocks - expressions in Scala
* visibility of variables in blocks
* local scoping (similar to let)
* semicolons (optional)
* tail recursion in Scala (only direct recursive calls are optimised @tailrec)
* function types (''f : Int => Int'')
* anonymous functions (''(x: Int, y: Int) => x + y'', '' x => x+x'')
* currying (''def f(x: Int, y: Int)(z: Int):Int = x+y+z'')
* higher-order functions (mapReduce implementation)
* classes and **methods**
class Rational(x: Int, y: Int) { // creates a Type as well as a constructor for the new type
def a = x
def b = y
}
val r = new Rational(1,2)
* ''toString'' and ''@override''
* the ''require'' (a precondition on the caller of a function) (equivalent to) and ''assert'' (check the code is right)
* **constructors**:
* multiple constructors:
class ... {
def this(x: Int) = this(x,1)
}
* infix notation for functions
r add s /*same as*/ r.add(s)
def < (param : Rational) /* symbolic identifiers may contain operator symbols */
def unary_- (...) /* to overload negation. Careful, white spaces can be interpreted as identifiers */
/* the precedence of an operator is determined by its first character */
/* precedence cannot be overridden by the programmer */
===== 3. Data representation ======
* object definitions - singleton classes ''object Empty extends IntSet''
* companion objects (one object per class)
* annotation ''@main def birthday'' - can be called directly from compilation ''scala birthday ...''
* ''println(s"Hello $name")''
* **dynamic binding**
* packages - organising sources - directories (not enforced by the fs)
import pack.Obj
* traits (similar to interfaces in Java, but can have parameters, contain fields and defined functions)
* object hierarchy in Scala
* exceptions (similar to Scala)
* **ADTs**:
* ''class Cons (val head: Int, val tail: List) extends... '' - value parameters
* type parameters (square brackets)
* generic functions ''def singleton[T] (elem: T) ...''
* **Scala is a pure OO language (unlike Java)!!**
* functions are implemented as objects
trait Function1 [A,B]:
def apply(x: A): B
f = new Function1[Int,Int]: //anonymous class
def apply(x: Int) = x * x
/* anonymous classes are equivalent to blocks that evaluate to an object*/
{ class $anonfun() extends Function1[Int,Int]:
def apply(x: Int) = x * x
$anonfun()
def f(x: Int): Boolean = ...
/* the above is not itself a function value. However, if it is used where a Function type is expected
it is converted automatically to the function value: */
(x: Int) => f(x)
// or expanded to
new Function[Int, Boolean]:
def apply(x: Int) = f(x)
===== 4. TDAs ======
Object-Oriented decomposition (the classical TDAs vs OO)
Functional decompositions (case classes)
def eval(e: Expr): Int = e match
case Number(n) => n
case Sum(e1,e2) => eval(e1) + eval(e2)
val l = 1 :: 2 :: 3 :: Nil
**Enums** (TDAs)
enum Expr:
case Var (s: String)
case Number (n: Int)
case Sum(e1: Expr, e2: Expr)
case Prod(e1: Expr, e2: Expr)
Type bounds in generics
def asseertAllPos [S <: IntSet] (r: S): S = ...