Last active
October 20, 2020 15:20
-
-
Save jgeek/c221b66f3b1941106e60a7cbd896a4ea to your computer and use it in GitHub Desktop.
scala notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
https://booksites.artima.com/programming_in_scala_4ed/examples/ | |
loan pattern: open a resource,operate on it, and then close the resource. | |
function literals, and function values | |
Scala supports first-class functions, which means you can express functions in | |
function literal syntax, i.e., (x: Int) => x + 1 , | |
and that functions can be represented by objects, which are called function values. | |
function literals and | |
values is that function literals exist in the source code, whereas function val- | |
ues exist as objects at runtime. | |
Every function value is an instance of some class that extends one of several FunctionN | |
traits in package scala , such as Function0 for functions with no parameters, Function1 for | |
functions with one parameter, and so on. Each FunctionN trait has an apply method used to | |
invoke the function. | |
target typing | |
currying | |
Any time you find a control pattern repeated in multiple parts of your | |
code, you should think about implementing it as a new control structure. | |
In any method invocation in Scala in which you’repassing in exactly one argument, you can opt to use curly braces to surround | |
the argument instead of parentheses. println { "Hello, world!" } | |
uniform access principle, says that client code should not be affected by | |
a decision to implement an attribute as a field or method. | |
empty-paren methods: | |
it is encouraged in Scala to define methods that take no parameters and have no side effects as parameterless methods. | |
Subtyping: means that a value of the subclass can be used wherever a value of the superclass is required. | |
Scala’s two namespaces are: | |
• values (fields, methods, packages, and singleton objects) | |
• types (class and trait names) | |
These “accidental overrides” are the most common manifestation of what | |
is called the “fragile base class” problem. The problem is that if you add new | |
members to base classes (which we usually call superclasses) in a class hier- | |
archy, you risk breaking client code. | |
subtyping polymorphism | |
universal polymorphism | |
The reason AnyRef alias exists, instead of just using the name java.lang.Object , is | |
because Scala was originally designed to work on both the Java and .NET platforms. On | |
.NET, AnyRef was an alias for System.Object . | |
one use of Nothing is that it signals abnormal termination. | |
traits use cases: widening thin interfaces to rich ones, and defining stackable modifica- | |
tions. | |
If you plan to distribute it in compiled form, and you expect outside | |
groups to write classes inheriting from it, you might lean towards using an | |
abstract class. The issue is that when a trait gains or loses a member, any | |
classes that inherit from it must be recompiled, even if they have not changed. | |
Package objects are frequently used to | |
hold package-wide type aliases (Chapter 20) and implicit conversions (Chap- | |
ter 21) | |
The ensuring method takes one argument, a predicate function that takes a re- | |
sult type and returns Boolean , and passes the result to the predicate. If the | |
predicate returns true, ensuring will return the result; otherwise, ensuring | |
will throw an AssertionError . | |
Pattern matching: | |
Scala uses a simple lexical rule for disambiguation: a simple name starting with | |
a lowercase letter is taken to be a pattern variable; all other references are | |
taken to be constants. | |
You can still use a lowercase name for a pattern constant, if you need | |
to, by using one of two tricks. First, if the constant is a field of some ob- | |
ject, you can prefix it with a qualifier. For instance, pi is a variable pattern, | |
but this.pi or obj.pi are constants even though they start with lowercase | |
letters. If that does not work (because pi is a local variable, say), you can al- | |
ternatively enclose the variable name in back ticks. For instance, `pi` would | |
again be interpreted as a constant, not as a variable: | |
scala> E match { | |
case `pi` => "strange math? Pi = " + pi | |
case _ => "OK" | |
} | |
res14: String = OK | |
The only exception to the erasure rule is arrays, because they are handled | |
specially in Java as well as in Scala. The element type of an array is stored | |
with the array value, so you can pattern match on it. | |
def isStringArray(x: Any) = x match { | |
case a: Array[String] => "yes" | |
case _ => "no" | |
} | |
Pattern guards | |
This fails because Scala restricts patterns to be linear: a pattern variable may | |
only appear once in a pattern. | |
def simplifyAdd(e: Expr) = e match { | |
case BinOp("+", x, y) if x == y => | |
BinOp("*", x, Number(2)) | |
case _ => e | |
} | |
def describe(e: Expr): String = (e: @unchecked) match { | |
case Number(_) => "a number" | |
case Var(_) | |
=> "a variable" | |
} | |
Working with Lists: | |
Lists are quite similar to arrays, but there are two important differences. | |
First, lists are immutable. That is, elements of a list cannot be changed | |
by assignment. Second, lists have a recursive structure (i.e., a linked list), 1 | |
whereas arrays are flat. | |
The list type in Scala is covariant. This means that for each pair of | |
types S and T , if S is a subtype of T , then List[S] is a subtype of List[T] . | |
For instance, List[String] is a subtype of List[Object] . | |
class Thermometer { | |
var celsius: Float = _ | |
def fahrenheit = celsius * 9 / 5 + 32 | |
def fahrenheit_= (f: Float) = { | |
celsius = (f - 32) * 5 / 9 | |
} | |
override def toString = s"${fahrenheit}F/${celsius}C" | |
} | |
an initializer “ = _ ” of a field assigns a zero | |
value to that field. The zero value depends on the field’s type. It is 0 for | |
numeric types, false for booleans, and null for reference types. This is the | |
same as if the same variable was defined in Java without an initializer. | |
Note that you cannot simply leave off the “ = _ ” initializer in Scala. If | |
you had written: | |
var celsius: Float | |
this would declare an abstract variable, not an uninitialized one. | |
four kinds of abstract member: val s,var s, methods, and types. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment