Coursera:Functional Programming Principles in Scala Cheet Sheet 翻译

Cheet Sheet

注:该文章为笔者学习MOOC上SCALA课程时所对照的备忘录,原翻译时通过markdown记录在有道云笔记上,csdn取消了在编辑时输入md的功能因此格式会有些奇怪。

 

(evaluation:类似于加载到内存中,进行计算)

Evaluation Rules

求值原则

Call by value: evaluates the function arguments before calling the function

应用序求值,在调用函数之前计算出参数的值

Call by name : evaluates the function first.and then evaluates the arguments if need be

正则序求值,首先编译函数,如果需要参数的值才会去计算

``def example = 2                        /evaluated when called /当被调用时才会编译``

``val example = 2                        //evaluated immediately 声明时就计算``

``lazy val example = 2                 //evaluated once when needed 只在需要的时候加载一次``

 

``def square(x: Double)               //call by value应用序求值``

``def square(x: => Double)          //call by name正则序求值``

``def myFct(bingdings: Int*) = {...} //bingdings is a sequence of int, containing a varying # of  arguments  bindings 是一个int型数据的序列,包括大量参数``

 

Higher order funcitons

高阶函数

These are functions that take a function as a parameter or return funcitons.

如下为参数为函数或返回值为函数的函数

``//sum() returns a function that takes two integers and returns an integer``

``//sum()函数返回一个具有两个Int输入参数,返回值也为Int类型的函数``

``def sum(f:Int => Int):(Int,Int) => Int = {``

`` def sum(a:Int, b: Int):Int = {...}``

`` sumf``

``}``

``//same as above .Its type is (Int =>Int) => (Int,Int)=> Int··

``//同上,类型为(Int =>Int) => (Int,Int)=> Int``

``def sum(f:Int => Int)(a:Int, b:Int): Int ={...}

``//Called like this``

``//如下方法调用``

``sum((x:Int) => x*x*x)``           //Anonymous function, i.e.  does not have a name  匿名函数``

``sum(x =>x *x *x )                  //same anonymous function with type inferred 类型推断的匿名函数``

``def cube(x:Int) = x*x*x``

``sum (x => x * x *x )(1,10)      //sum of cubes from 1 to 10  求输入参数1-10的和``

``sum(cube)(1,10)                   //same as above 同上``

 

Currying

函数柯里化

Converting a function with multiple arguments into a function with a single argument that returns another function

将一个具有多个输入参数的函数转变为另一个具有唯一输入参数的函数```

```

object exercise{

// def product(f:Int => Int)(a:Int, b:Int):Int =

// if(a > b) 1

// else f(a) * product(f)(a+1, b)

//

// product(x => x * x)(3, 4)         //res = 144

def mapReduce(f:Int=>Int,combine:(Int,Int) => Int.zero:Int)(a:Int,b:Int):Int=

if(a>b) zero

else combine(f(a),mapreduce(f,combine,zero)(a+1,b)

 

def product(f:Int=>Int)(a:Int,b:Int) :Int = mapReduce(f, (x, y) => x * y, 1)(a, b)

product(x => x * x)(3, 4) //res=144

}

```

 

`` def f(a:Int,b:Int):Int     //uncurried version (type is (Int,Int) => Int) ``

``def f(a:int)(b:int):Int     //curried version (type is Int=>Int=>Int)

 

``Class MyClass(x:Int,y:Int){     //Defines a new type MyClass with a constructor``

`` require(y > 0,"y ust be positive:")   //precondition, triggering an IllegalArgumentException if not met``

``def this(x:Int) = {...}      //auxiliary  constructor``

``def nb1 = x      //public method computed ecery time it is called``

``def nb2 = y``

``private def test(a:Int):Int ={...}    //private method``

``val nb3 = x + y    //computed only once``

``override def toString =              //override method ``

`` member1 + “,”+ member2``

``}``

``new MyClass(1,2)  //create a new object of tyoe``

 

this references the current object ,assert(<condition>) issues AssertionError if condition is not met.See scala.Predef for require,assume and assert.

引用当前对象,如果条件不符合声明断言错误(AssertionError),具体查看scala.Predef 类中assume 和assert 部分

```

final def assert(assertion:Boolean, message: => Any):Unit

Tests an expresstion, throwing an AssertionError if false.

```

```

def assert(assertion:Boolen):Unit

Tests an expression,throwing an AssertionError if false.

```

```

final def assume(assumption:Boolean, message: => Any):Unit

Tests an expression,thorwing an AssertionError if false

```

```

def assume(assumption:Boolean, message: => Any):Unit

Tests an expression,thorwing an AssertionError if false

```

```

final def require(requirement:Boolean, message:=>Any):Unit

Tests an expression, throwing an IllegalArgumentException if false

```

```

def require(requirement:Boolean, message:=>Any):Unit

Tests an expression, throwing an IllegalArgumentException if false

```

 

Operators

运算符

 

myObject myMethod 1 is the same as calling myObject.myMethod(1)

myObject myMethod 1 等价于 myObject.myMethod(1)

Operator(i.e.function) names can be alphanumeric,symbolic(e.g.x1,*,+?%&,vector_++.counter_=)

运算符(函数)名字可以是字母数字或符号(如x1,*,+?%&,vector_++.counter_=)

The precedence of an operator is determined by its first character, withthe following increasing order of priority:

运算符的优先级由他的第一个字符决定,下面的字符优先级逐个递增

```

(all letters)

|

^

&

< >

= !

:

+ -

* / %

(all other special characters)

```

The associativity of an operator is determined by its last character:Right-associative if ending with;,Left-associative otherwise

运算符的结合律是由他最后一个字符决定的,如果以‘:(冒号)‘结尾则右关联,否则左关联

Note that assignment operators have lowest precedence.

注意赋值运算符的优先级最低。

 

class C(x1,...,xn){... def f(y1,...,yn) =b...}

`The formal paramters of the class are x1,...,xn

`The class defines a method f with formal parameters y1,...,yn

 

expression new C(v1,....,vm).f(w1,...,wn) is rewritten to :

[w1/y1,...,wn/yn][v1/x1,...,vm/xm][newC(v1,...vm)/this]b

 

eg:

1. new Rational(1,2).numer

-> [1/x,2/y][][new Rational(1,2)/this]x

=1

2. new Rational(1,2).less(new Rational(2,3))

->[1/x,2/y][newRational(2,3)/that][new Rational(1,2)/this]

this.numer * that.denom < that,numer * this.denom

=new Raional(1,2).numer * new Rational(2,3).denom <

new Rational(2,3).numer * new Rational(1,2).denom

-> 1 * 3 < 2 * 2

-> true

Class hierarchies

类的层级

 

···

abstract class TopLevel {     // abstract class 

  def method1(x: Int): Int   // abstract method 

  def method2(x: Int): Int = { ... } 

}

 

class Level1 extends TopLevel { 

  def method1(x: Int): Int = { ... } 

  override def method2(x: Int): Int = { ...} // TopLevel's method2 needs to be explicitly overridden 

}

 

object MyObject extends TopLevel { ... } // defines a singleton object. No other instance can be created

···

To create an runnable application in Scala:

创建一个可执行的Scala应用

 

```

object Hello { 

  def main(args: Array[String]) = println("Hello world") 

}

```

or

```

object Hello extends App {

  println("Hello World")

}

```

 

Class Organization

 

·Classes and objects are organized in packages (package myPackage).

类和对象包括在包中。

·They can be referenced through import statements(import myPackage.MyClass, importmyPackage._, import myPackage.{MyClass1,MyClass2}, import myPackage.{MyClass1=>A})

他们可以通过import 来引用,引用格式如(import myPackage.MyClass, importmyPackage._, import myPackage.{MyClass1,MyClass2}, import myPackage.{MyClass1=>A})

·They can also be directly referenced in the code with the fully qualified name(new myPackage.MyClass1)

他们也可以在代码中通过全名(new myPackage.MyClass1)来引用

·All members of packages scala and java.lang as well as all members of the object scala.Predef are automatically imported

在scala包和java.lang包中的对象以及scala.Predef包中的对象都会被自动引用

·Traits are similar to Java interfaces, except they can have non-abstract members:trait Planar{...}class Square extends Shape with Planer

特性(traits)与java中的接口类似,但是可以有非抽象的成员:可以这样使用:trait Planar{...}class Square extends Shape with Planer

·General object hierarchy:

通用对象层级:

-scala.Any base type fo all types,Has methods hashCode and toString that can be overriden

-scala.Any 是所有类的基类,方法hashCode和toString 应该被重写

--scala.AnyVal base type of all primitive types.(scala.Double, scala.Float, etc)

--scala.AnyVal 是所有私有基础类型的基类(如scala.Double,scala.Float)

-scala.AnyRef base type of all reference types.(alias of java.lang.Object, supertype of java.lang.String, scala.List, any user-defined class)

-scalaAnyRef 是所有引用类型的基类(是java.lang.Object类的别名, supertype of java.lang.String, scala.List, any user-defined 类等)

-scaka.Null is a subtype of any scala.AnyRef(null is the only instance of type Null), and scala.Nothing is a subtype of any other type without any instance.

-scaka.NUll 是scala.Any的子类(null 是Null类型的唯一实例),scala.Nothing是所有其他没有没有实例类型的子类

 

Type Parameters

类型参数

Similar to C++ templates or Java generics. These can apply to classes, traits or functions.

与C++中的模板或java中的泛型类似,他们可以被应用到类、特性或函数中。

```

class MyClass[T](arg1: T) { ... } 

new MyClass[Int](1) 

new MyClass(1)   // the type is being inferred, i.e. determined based on the value arguments  类型是根据值参数的类型被推断

```
It is possible to restrict the type being used, e.g.

可以限制使用的类型,如:

```

def myFct[T <: TopLevel](arg: T): T = { ... } // T must derive from TopLevel or be TopLevel  T是TopLevel的子类或者是TopLevel类

def myFct[T >: Level1](arg: T): T = { ... }   // T must be a supertype of Level1  类T是Level的父类

def myFct[T >: Level1 <: Top Level](arg: T): T = { ... }

```

Variance

变型

Given A <: B

If C[A] <: C[B], C is covariant

If C[A] >: C[B], C is contravariant

Otherwise C is nonvariant

已知 A是B的子类 如果C[A]是C[B]的子类,那么C是协变的,如果C[A]是C[B]的父类,那么C是逆变的,否则C是不变的

```

class C[+A] { ... } // C is covariant  协变

class C[-A] { ... } // C is contravariant  逆变

class C[A]  { ... } // C is nonvariant  不变

```

For a function, if A2 <: A1 and B1 <: B2, then A1 => B1 <: A2 => B2.

对于一个函数来说如果A2是A1的子类,并且B1是B2的子类,那么以A1为输入参数类型,B1为返回值类型的函数是以A2为输入参数类型,B2为返回值类型的函数的子类。

Functions must be contravariant in their argument types and covariant in their result types, e.g.

要求函数的参数类型符合逆变,返回值符合协变,例如:

```

trait Function1[-T, +U] {

  def apply(x: T): U

} // Variance check is OK because T is contravariant and U is covariant

 

class Array[+T] {

  def update(x: T)

} // variance checks fails

```

 

if A<:B . then everything one can to do with a value of  type B one should alse be able to do with a value of type A

 

=>Let q(x) be a property provable about objects x of type B.Then q(y) should be provable for objects y of type A where A<:B.

 

 

Pattern Matching

模式匹配

Pattern matching is used for decomposing data structures:

模式匹配用于分解数据结构

 

```

unknownObject match {

  case MyClass(n) => ...

  case MyClass2(a, b) => ...

}

```

Here are a few example patterns

一下是一些例子

```

(someList: List[T]) match {

  case Nil => ...          // empty list  匹配空列表

  case x :: Nil => ...     // list with only one element 匹配只有一个元素的列表

  case List(x) => ...      // same as above 同上

  case x :: xs => ...      // a list with at least one element. x is bound  to the head, 匹配头部至少有一个元素为x的列表

                           // xs to the tail. xs could be Nil or some other  list.  ’xs'在末尾,xs可以是空或者其他列表

  case 1 :: 2 :: cs => ... // lists that starts with 1 and then 2 匹配列表开头为1,2 的列表

  case (x, y) :: ps => ... // a list where the head element is a pair 匹配开头为一个元组的列表

  case _ => ...            // default case if none of the above matches 匹配其余情况

}

```

The last example shows that every pattern consists of sub-patterns: it only matches lists with at least one element, where that element is a pair. x and y are again patterns that could match only specific types.

最后一个例子说明每个模式都由子模式构成,他只匹配至少具有一个元素的列表,x和y只能匹配特定的类型

Options

选项

Pattern matching can also be used for Option values. Some functions (like Map.get) return a value of type Option[T] which is either a value of type Some[T] or the value None:

模式匹配也可以被用来选择值,一些函数(如Map的get方法)返回值的类型是一个类型为T的可选值的容器,如果值存在Option[T]就是Some[T],否则就是None

```

val myMap = Map("a" -> 42, "b" -> 43)

def getMapValue(s: String): String = {

  myMap get s match {

    case Some(nb) => "Value found: " + nb

    case None => "No value found"

  }

}

getMapValue("a")  // "Value found: 42"

getMapValue("c")  // "No value found"

```

Most of the times when you write a pattern match on an option value, the same expression can be written more concisely using combinator methods of the Option class. For example, the function getMapValue can be written as follows:

大多数时候,当你在可选值上编写模式匹配时,可以使用Option类的组合方法,getMapValue方法可以写为:

```

def getMapValue(s: String): String =

  myMap.get(s).map("Value found: " + _).getOrElse("No value found")

```

Pattern Matching in Anonymous Functions

模式匹配在匿名函数中的应用

Pattern matches are also used quite often in anonymous functions:

模式匹配在匿名函数中也常常被使用

```

val pairs: List[(Char, Int)] = ('a', 2) :: ('b', 3) :: Nil

val chars: List[Char] = pairs.map(p => p match {

  case (ch, num) => ch

})

```

Instead of p => p match { case ... }, you can simply write {case ...}, so the above example becomes more concise:

可以用{case ...}而不是使用 p=>p match {case...},那么上面的例子可以写为

```

val chars: List[Char] = pairs map {

  case (ch, num) => ch

}

```

 

Collections

集合

Scala defines several collection classes:

scala定义了很多集合类

Base Classes

基类

  • Iterable (collections you can iterate on)迭代器
  • Seq (ordered sequences)顺序表
  • Set 集合
  • Map (lookup data structure) 查找数据结构

Immutable Collections

不可变集合

  • List (linked list, provides fast sequential access)
  • Stream (same as List, except that the tail is evaluated only on demand)
  • Vector (array-like type, implemented as tree of blocks, provides fast random access)
  • Range (ordered sequence of integers with equal spacing)
  • String (Java type, implicitly converted to a character sequence, so you can treat every string like a Seq[Char])
  • Map (collection that maps keys to values)
  • Set (collection without duplicate elements)

Mutable Collections

  • Array (Scala arrays are native JVM arrays at runtime, therefore they are very performant)
  • Scala also has mutable maps and sets; these should only be used if there are performance issues with immutable types

 

```

val fruitList = List("apples", "oranges", "pears")

// Alternative syntax for lists

val fruit = "apples" :: ("oranges" :: ("pears" :: Nil)) // parens optional, :: is right-associative

fruit.head   // "apples"

fruit.tail   // List("oranges", "pears")

val empty = List()

val empty = Nil

 

val nums = Vector("louis", "frank", "hiromi")

nums(1)                     // element at index 1, returns "frank", complexity O(log(n))

nums.updated(2, "helena")   // new vector with a different string at index 2, complexity O(log(n))

 

val fruitSet = Set("apple", "banana", "pear", "banana")

fruitSet.size    // returns 3: there are no duplicates, only one banana

 

val r: Range = 1 until 5 // 1, 2, 3, 4

val s: Range = 1 to 5    // 1, 2, 3, 4, 5

1 to 10 by 3  // 1, 4, 7, 10

6 to 1 by -2  // 6, 4, 2

 

val s = (1 to 6).toSet

s map (_ + 2) // adds 2 to each element of the set

 

val s = "Hello World"

s filter (c => c.isUpper) // returns "HW"; strings can be treated as Seq[Char]

 

// Operations on sequences

val xs = List(...)

xs.length   // number of elements, complexity O(n)

xs.last     // last element (exception if xs is empty), complexity O(n)

xs.init     // all elements of xs but the last (exception if xs is empty), complexity O(n)

xs take n   // first n elements of xs

xs drop n   // the rest of the collection after taking n elements

xs(n)       // the nth element of xs, complexity O(n)

xs ++ ys    // concatenation, complexity O(n)

xs.reverse  // reverse the order, complexity O(n)

xs updated(n, x)  // same list than xs, except at index n where it contains x, complexity O(n)

xs indexOf x      // the index of the first element equal to x (-1 otherwise)

xs contains x     // same as xs indexOf x >= 0

xs filter p       // returns a list of the elements that satisfy the predicate p

xs filterNot p    // filter with negated p

xs partition p    // same as (xs filter p, xs filterNot p)

xs takeWhile p    // the longest prefix consisting of elements that satisfy p

xs dropWhile p    // the remainder of the list after any leading element satisfying p have been removed

xs span p         // same as (xs takeWhile p, xs dropWhile p)

 

List(x1, ..., xn) reduceLeft op    // (...(x1 op x2) op x3) op ...) op xn

List(x1, ..., xn).foldLeft(z)(op)  // (...( z op x1) op x2) op ...) op xn

List(x1, ..., xn) reduceRight op   // x1 op (... (x{n-1} op xn) ...)

List(x1, ..., xn).foldRight(z)(op) // x1 op (... (    xn op  z) ...)

 

xs exists p    // true if there is at least one element for which predicate p is true

xs forall p    // true if p(x) is true for all elements

xs zip ys      // returns a list of pairs which groups elements with same index together

xs unzip       // opposite of zip: returns a pair of two lists

xs.flatMap f   // applies the function to all elements and concatenates the result

xs.sum         // sum of elements of the numeric collection

xs.product     // product of elements of the numeric collection

xs.max         // maximum of collection

xs.min         // minimum of collection

xs.flatten     // flattens a collection of collection into a single-level collection

xs groupBy f   // returns a map which points to a list of elements

xs distinct    // sequence of distinct entries (removes duplicates)

 

x +: xs  // creates a new collection with leading element x

xs :+ x  // creates a new collection with trailing element x

 

// Operations on maps

val myMap = Map("I" -> 1, "V" -> 5, "X" -> 10)  // create a map

myMap("I")      // => 1 

myMap("A")      // => java.util.NoSuchElementException 

myMap get "A"   // => None

myMap get "I"   // => Some(1)

myMap.updated("V", 15)  // returns a new map where "V" maps to 15 (entry is updated)

                        // if the key ("V" here) does not exist, a new entry is added

 

// Operations on Streams

val xs = Stream(1, 2, 3)

val xs = Stream.cons(1, Stream.cons(2, Stream.cons(3, Stream.empty))) // same as above

(1 to 1000).toStream // => Stream(1, ?)

x #:: xs // Same as Stream.cons(x, xs)

         // In the Stream's cons operator, the second parameter (the tail)

         // is defined as a "call by name" parameter.

         // Note that x::xs always produces a List

```

 

Pairs (similar for larger Tuples)

```

val pair = ("answer", 42)   // type: (String, Int)

val (label, value) = pair   // label = "answer", value = 42 

pair._1 // "answer" 

pair._2 // 42 

```

For-Comprehensions

为了方便理解

A for-comprehension is syntactic sugar for map, flatMap and filter operations on collections.

The general form is for (s) yield e

一个为了方便理解Map flatmap  filter 等对于集合操作的语法糖,通常的格式如for(s) yield e

  • s is a sequence of generators and filters
  • s 是一个生成器和过滤器的序列
  • p <- e is a generator
  • p<-e 是一个生成器
  • if f is a filter
  • 如果f是一个过滤器
  • If there are several generators (equivalent of a nested loop), the last generator varies faster than the first
  • 如果有几个生成器 相当于一个嵌套循环,那么最后一个生成器变化的速度大于第一个生成器
  • You can use { s } instead of ( s ) if you want to use multiple lines without requiring semicolons
  • 你可以使用{s}而不是(s)如果你希望在其中编写多行,而不使用分号
  • e is an element of the resulting collection
  • e 是结果集中的一个元素

 

```

// list all combinations of numbers x and y where x is drawn from

// 1 to M and y is drawn from 1 to N

for (x <- 1 to M; y <- 1 to N)

  yield (x,y)

```

is equivalent to

等价于

```

(1 to M) flatMap (x => (1 to N) map (y => (x, y)))

```

Translation Rules

转换规则

A for-expression looks like a traditional for loop but works differently internally

一个for表达式看起来像是传统的for循环,但是其中的工作方式不尽相同

for (x <- e1) yield e2 is translated to e1.map(x => e2)

for (x <- e1 if f) yield e2 is translated to for (x <- e1.filter(x => f)) yield e2

for (x <- e1; y <- e2) yield e3 is translated to e1.flatMap(x => for (y <- e2) yield e3)

This means you can use a for-comprehension for your own type, as long as you define map, flatMap and filter.

这意味着你可以根据你的理解选择应用的类型,只要定义了map,flatMap,filter操作

 

example2:

```

for { 

  i <- 1 until n 

  j <- 1 until i 

  if isPrime(i + j) 

} yield (i, j) 

```

is equivalent to

等价于

```

for (i <- 1 until n; j <- 1 until i if isPrime(i + j))

    yield (i, j) 

```

is equivalent to

等价于

```

(1 until n).flatMap(i => (1 until i).filter(j => isPrime(i + j)).map(j => (i, j)))

```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值