# Extracts of Programming in Scala

CHAPTERS 4 - 6

## Chapter 4

• Once you define a class, you can create objects from the class blueprint with the keyword new.
• Fields are also known as instance variables, because every instance gets its own set of the variables.
• val acc = new CheckSumAccumulator: you were able to mutate the object acc referred to, even though acc is a val. What you can't do with acc, given that it is a val, not a var, is reassign a different object to it.
• The first step is to prevent outsiders from accessing the fields directly by making the fields private. private var sum = 0
• Public is Scala's default access level.
• One important characteristics of method parameters in Scala is that they are vals, not vars.
• In the absence of any explicit return statement, a Scala method returns the last value computed by the method.
• def add(b: Byte) = sum += b: although the Scala compiler will correctly infer the result types of the add, readers of the code will also need to mentally infer the result types by studying the body of the method. As a result it is often better to explicitly provide the result types of public methods declared in a class even when the compiler would infer it for you.
• A method that is executed only for its side effects is known as a procedure.
• A semicolon is required if you write multiple statements on a single line: val s = "hello"; println(s)
• It is a common Scala style to put the operators at the end of the line instead of the beginning:
x +y +z
• Classes in Scala cannot have static members.
• A singleton object definition looks like a class definition, except instead of the keyword class you use the keyword object.
• When a singleton object shares the same name with a class, it is called that class's companion object. You must define both the class and its companion object in the same source file.
• If you are a Java programmer, one way to think of singleton objects is as the home for any static methods you might have written in Java. You can invoke methods on singleton objects using a similar syntax: the name of the singleton object, a dot, and the name of the method.
• One difference between classes and singleton objects is that singleton objects cannot take parameters, whereas classes can. Because you don't instantiate a singleton object with the new keyword, you have no way to pass parameters to it. Each singleton object is implemented as an instance of a synthetic class referenced from a static variable, so they have the same initialization semantics as Java statics. In particular, a singleton object is initialized the first time some code accesses it.
• A singleton object that does not share the same name with a companion class is called a standalone object.
• To run a Scala program, you must apply the name of a standalone singleton object with a main method that takes one parameter, an Array[String], and has a result type of Unit.
• import ChecksumAccumulator.calculate is an import of the calculate method defined in the ChecksumAccumulator object. This import statement allows you to use the method's simple name in the rest of the file.
• Scala implicitly imports members of packages java.lang and scala, as well as the members of a singleton object named Predef, into every Scala source file. Predef, which resides in package scala, contains many useful methods. For example, when you say println in a Scala source file, you're actually invoking println on Predef.
• Neither ChecksumAccumulator.scala nor Summer.scala are scripts, because they end in a definition. A script, by contrast, must end in a result expression. Thus if you try to run Summer.scala as a script, the Scala interpreter will complain that Summer.scala does not end in a result expression.
• scalac ChecksumAccumulator.scala Summer.scala compiles your source files, but there may be a perceptible delay before the compilation finishes. The reason is that every time the compiler starts up, it spends time scanning the contents of jar files and doing other initial work before it even looks at the fresh source files you submit to it. For this reason, the Scala distribution also includes a Scala compiler daemon called fsc. You use it like this: fsc ChecksumAccumulator.scala Summer.Scala
• If you ever want to stop the fsc daemon, you can do so with fsc -shutdown
• To use the app trait, you first write "extends App" after the name of your singleton object. Then instead of writing a main method, you place the code you would have put in the main method directly between the curly braces of the singleton object. You can access command-line arguments via an array of strings named args. That's it. You can compile and run this application just like any other.

## Chapter 5

• Integer literals that start with a $0$, such as $031$, do not compile.
• If the number begins with a 0x or 0X, it is hexadecimal (base $16$), and may contain $0$ through $9$ as well as upper or lowercase digits $A$ through $F$.
• Floating point literals are made up of decimal digits, optionally containing a decimal point, and optionally followed by an $E$ or $e$ and an exponent. [...] The exponent portion means the power of $10$ by which the other portion is multiplied. Thus, $1.2345e1$ is $1.2345$ times $10^1$, which is $12.345$. If a flowing-point literal ends in an $F$ or $f$, it is a Float; otherwise it is a Double. Optionally, a Double floating-point literal can end in D or d.
• Scala includes a special syntax for raw strings. You start and end a raw string with three double quotation marks in a row ("""). The interior of a raw string may contain any characters whatsoever, including newlines, quotation marks, and special characters, except of course three quotes in a row.
• Symbol literals are typically used in situations where you would use just an identifier in a dynamically typed language.
• println(s"Hello, $name!")$ Thesinterpolator will evaluate each embedded expression, invoketoString on each result, and replace the embedded expressions in the literal with those results. For single-variable expressions, you can often just place the variable name after the dollar sign. If the expression includes non-identifier characters, you must place it in curly braces, with the open curly brace immediately following the dollar sign.
• The f interpolator allows you to attach printf-style formatting instructions to embedded expressions. f"${math.Pi}%.5f" • The indexOf method searches the string for the first occurrence of the specified character and returns its index or -1 if it doesn't find the character. • String offers an overloaded indexOf method that takes two parameters, the character for which to search and an index at which to start. [...] Whenever you call a method that takes multiple arguments using operator notation, you have to place those arguments in parentheses. • Prefix and postfix operators are unary: they take just one operand. The name of the method has "unary_" prepended to the operator character. • The only identifiers that can be used as prefix operators are +, -, !, and ~. • You may be wondering how short-circuiting can work given operators are just methods. Normally, all arguments are evaluated before entering a method, so how can a method avoid evaluating its second argument? The answer is that all Scala methods have a facility for delaying the evaluation of their arguments, or even declining to evaluate them at all. The facility is called by-name parameters. • You can compare two objects that have different types. List(1,2,3) == "Hello" • == has been carefully crafted so that you get just the equality comparison you want in most cases. This is accomplished with a very simple rule: First check the left side for null. If it is not null, call the equals method. Since equals is a method, the precise comparison you get depends on the type of the left-hand argument. Since there is an automatic null check, you do not have to do the check yourself. • Scala provides a facility for comparing reference equality, as well, under the name eq. However, eq and its opposite, ne, only apply to objects that directly map to Java objects. • Scala decides precedence based on the first character of the methods used in operator notation (there's one exception to this rule). If the method name starts with a $*$, for example, it will have a higher precedence than a method that starts with a +. Similarly, a +++ b *** c will be evaluated a +++ (b *** c), because the *** method has a higher precedence than the +++ method. • The one exception to the precedence rule, alluded to earlier, concerns assignment operators, which ends in an equals character. If an operator ends in an equals character (=), and the operator is not one of the comparison operators <=, >=, ==, or !=, then the precedence of the operator is the same as that of simple assignment (=). That is, it is lower than the precedence of any other operator. • The associativity of an operator in Scala is determined by its last character. Any method that ends in a ; character is invoked on its right operand, passing in the left operand. Methods that end in any other character are the other way around: They are invoked on their left operand, passing the right operand. So a * b yields a.*(b), but a ::: b yields b.:::(a) ## Chapter 6 • Functional objects are objects that do not have any mutable state. • If a class doesn't have a body, you don't need to specify empty curly braces. • class Rational(n: Int, d: Int) The identifiers n and d in the parentheses after the class name, Rational, are called class parameters. The Scala compiler will gather up these two class parameters and create a primary constructor that takes the same two parameters. • Immutable objects make safe hash table keys. If a mutable object that is mutated after it is placed into a HashSet, for example, that object may not be found the next time you look into the HashSet. • The main disadvantage of immutable objects is that they sometimes require a large object graph be copied, whereas an update could be done in its place. In some cases this can be awkward to express and might also cause a performance bottleneck. As a result, it is not uncommon for libraries to provide mutable alternatives to immutable classes. • Classes can take parameters directly in Scala. • The Scala compiler will compile any code you place in the class body, which isn't part of a field or a method definition, into the primary constructor. • A more useful implementation of toString would print out the values of the Rational's numerator and denominator. You can override the default implementation by adding method toString to class Rational, like this: override def toString = n + "/" + d • One of the benefits of object-oriented programming is that it allows you to encapsulate data inside objects so that you can ensure that the data is valid throughout its lifetime. • A precondition is a constraint on values passed into a method or constructor, a requirement which callers must fulfill. require(d != 0) • require will prevent the object from being constructed by throwing an IllegalArgumentException. • Although class parameters n and d are in scope in the code of your add method, you can only access their value on the object on which add was invoked. Thus, when you say n or d in add's implementation, the compiler is happy to provide you with the values for these class parameters. But it won't let you say that.n or that.d because that does not refer to the Rational object on which add was invoked. To access the numerator and denominator on that, you'll need to make them into fields. • Constructors other than the primary constructor are called auxiliary constructors. def this(n: Int) = this(n, 1) • The first statement in every auxiliary constructor in every Scala class will have the form "this(...)". The invoked constructor is either the primary constructor, or another auxiliary constructor that comes textually before calling constructor. The net effect of this rule is that every constructor invocation in Scala will end up eventually calling the primary constructor of the class. The primary constructor is thus the single point of entry of a class. • The Scala compiler will place the code for the initializers of fields into the primary constructor in the other in which they appear in the source code. • The $ character also counts as a letter; however, it is reserved for identifiers generated by the Scala compiler. Identifiers in user programs should not contain $ characters, even though it will compiler; if they do, this might lead to name clashes with identifiers generated by the Scala compiler. • Scala follows Java's convention of suing camel-case identifiers, such as toString and HashSet. Camel-case names of fields, method parameters, local variables, and functions should start with a lower case letter, for example: length, flatMap, and s. Camel-case names of classes and traits should start with an upper case letter, for example: BitInt, List, and UnbalancedTreeMap. • In Java, the convention is to give constant names that are all upper case, with underscores separating the words, such as MAX_VALUE or PI. In Scala, the convention is merely that the first character should be upper case. Thus, constants named in the Java style, such as X_OFFSET, will work as Scala constants, but the Scala convention is to use camel case for constants, such as XOffset. • The Scala compiler will internally "mangle" operator identifiers to turn them into legal Java identifiers with embedded $ characters. For instance, the identifier :-> would be represented internally as $colon$minus\$greater. If you ever wanted to access this identifier from Java code, you'd need to use this internal representation.
• A mixed identifier consists of an alphanumeric identifier, which is followed by an underscore and an operator identifier. For example, unary_+ used as a method name defines a unary + operator.
• A literal identifier is an arbitrary string enclosed in back ticks. This works even if the name contained in the back ticks would be a Scala reserved word. A typical use case is accessing the static yield method in Java's Thread class. You cannot write Thread.yield() because yield is a reserved word in Scala. However, you can still name the method in back ticks, e.g.,
xxxxxxxxxxThread.yield()
• In every case, the chosen overloaded version is the one that best matches the static types of the arguments. Sometimes there is no unique best matching version; in that case the compiler will give you an "ambiguous reference" error.
• You can create an implicit conversion that automatically converts integers to rational numbers when needed. Try adding this line in the interpreter
xxxxxxxxxximplicit def intToRational(x: Int) = new Rational(x)
• For an implicit conversion to work, it needs to be in scope. If you place the implicit method definition inside class Rational`, it won't be in scope in the interpreter. For now, you'll need to define it directly in the interpreter.