Study note 3 of the chapter 6, 7, 8, 9, and 10 of the book: Programming In Scala, 4th Edition.

Chapter 6: Functional Objects

Functional objects don’t have any mutable state. Function objects are simple (no state), sharable, thread-safe and safe hash keys. The main disadvantage is the copy of a large immutable object could be slow.

Class parameters are used to create a primary constructor. The {} are optional if the class body is empty. Any code in the class body is part of the primary constructor.

Use required(precondition) to check a precondition. If it is false, an IllegalArgumentException is throwed.

An auxiliary constructor must first call an auxiliary constructor or a primary constructor as its first action. Only the primary constructor can call a super class constructor.

There are four types of identifiers:

  • An alphanumeric identifier starts with a letter or underscore, which followed by letters, digits, or underscores. The $ letter are reserved for compiler.
  • An operator identifier consists of one or more operator characters such as +, -, *, :, ?, ~, #, <, >
  • A mixed identifier consists of an alphanumeric identifier followed by an underscore and an operator identifer. For example, unary_+ defines a unary + operator. myvar_= is used as a method name for assignment operator.
  • A literal identifier is an abritrary string enclosed in back ticks.

Chapter 7: Built-in Control Structures

Scala has 6 control structures: if, while, for, try, match and function call. They all result in values.

The while construct, called a loop, results a unit value whose type is Unit and is written as (). It should be avoide if possible.

The for expression works with any kind of collections. The x <- xs is called a generator that generates a new val x value. A expression can have one or more filters and can be nested. If you use for (), nested loops are separated by ;. If you use for {}, the parentheses can be left off. It also support mid-stream variable bindings, leaving off the val keyword. The for clauses yield body produces a new collection. for can run a code block or yield values.

The result of the throw expression has a type of Nothing. The try-catch-finally expression results in a value that has type of the try clause if no exception is thrown or the reelevant catch clause is an excetpion is caught. If an exception is throw but not caught, the expression has no result. The value computed in the finally clause if dropped. However, if the finally clause uses an explicit return statement or throws an exception, the returned value or exception will overrule any previous one. There is no checked exception in Scala.

Chapter 8: Functions and Closures

Functions

Scala offers several ways to define functions: object method, nested function, and function literal(function value).

A local fuinction can use its enclosing function’s parameters.

You can define function literals using => keyword, called right arrow or rocket. A fucntion literal is instantiated at runtime and is called a function value and exists as an object at runtime. In implementation, every function value is an instance of a class extending on of several scala.FunctionN trait. Each FunctionN trait has an apply method used to invoke the function.

Short forms of function literals:

  • Leaving out the parameter types when the target typing is known in the place of function literals.
  • Leaving out parentheses if there is a paremater and its type is left out.
  • Use _ as placeholders for one or more parameters, so long as each parameter appears only one time within the function literal.

You define a partially applied function by using _ to replace one or more or all arguments needed by the function. A partially applied function is a function value that can be assigned and passed around.

Practically, a Scala programmer only needs to know the following three rules to use functions and methods properly:

  • Methods defined by def and function literals defined by => are functions. It is defined in page 143, Chapter 8 in the book of Programming in Scala, 4th edition.
  • Function values are objects that can be passed around as any values. Function literals and partially applied functions are function values.
  • You can leave off the underscore of a partially applied function if a function value is required at a point in the code. For example: someNumber.foreach(println)

Closures

A variable is a bound variable if it is defined as its function’s parameter. A variable is a free variable if it is not defined in the function’s parameter.

A function literal with no free varialbes is called a closed term. A function literal with free variables is called an open term. The term is a bit of code.

A function value created at runtime from a closed term is called a closure becausse it needs to close the open term by binding all free variables. Scala’s closure capture variables themselves, not the value to which variables refer.

Repeated Parameters

The last pareameter can be repeated by denoting an asterisk after the type of the parameter as args: T*. Inside the function, the type of the repeated parameter is a Seq[T].

To passan array as a repeated parameter, you need to append the array argument with a colon and an _* symbol, like seq: _*.

Named argurment allows you to pass arguments to a function in different order. Scala support default parameter values.

Chapter 9: Control Abstraction

Methods such as exists are looping construct.

A curried function is applied to some of its argument lists. The last argument can be called using curly braces.

Only function parameters can have a by-name type that is defined a => T, instead of () => T. A function value will be created whose apply method will evaluate the argument express.

Chapter 10: Composition and Inheritance

A member is abstract if it is declared but its implementation is not defined.

It is a convention that parameterless methods don’t have side effects that change a mutable state or perform an IO operation. Empty-paren metehods are used for methods that have side effects.

val fields are pre-computed once when an object is initialized.

Scala has only two namespaces: values (fields, methods, packages, and singleton objects) and types (classes and traits).

Use val or var, optionally with modifiers (private, protected, and override), to define `parameteric fields.

Generally you should prefer composition to inheritance. To use inheritance, there are two conditions: there is an is-a relationship and the client want to sue the super class type.