Scala cheetsheet,小抄,语法整理


Scala的求值规则:

传值: 在函数调用之前求值

传名字: 先对函数求值,然后根据需要对参数求值


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(bindings: Int*) = { ... } // bindings is a sequence of int, containing a varying # of arguments


高阶函数:

高阶函数可以接受函数作为参数,或者返回函数

// sum() returns a function that takes two integers and returns an integer  
// sum()返回一个带两个整数为参数,返回一个整数的函数
def sum(f: Int => Int): (Int, Int) => Int = {  
  def sumf(a: Int, b: Int): Int = {...}  
  sumf  
} 

// same as above. Its type is (Int => Int) => (Int, Int) => Int  
//和上边的一样,它的类型是 <span style="font-family: Arial, Helvetica, sans-serif;">(Int => Int) => (Int, Int) => Int  </span>

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     同样的带类型推导的匿名函数
</pre><pre name="code" class="java">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 


柯里化

讲一个带多个参数的函数转换为一个带一个参数返回另外一个函数的函数

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)

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  顶一个带构造函数的新类型MyClass,
  require(y > 0, "y must be positive")    // precondition, triggering an IllegalArgumentException if not met  前置条件,如果要求不符合
<span style="white-space:pre">							</span>//这触发一个IllegalArgumentException
  def this (x: Int) = { ... }             // auxiliary constructor   //辅助构造函数
  def nb1 = x                             // public method computed every 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 =                 // overridden method  重写的方法
      member1 + ", " + member2 
  }

new MyClass(1, 2) // creates a new object of type     新建一个类型的对象

这个引用当前对象,assert(<condition>) 如果条件不符合就造成一个AssertionError。 参考scala.Predef的require, assume和assert


运算符:

myObject myMethod 1 和调用 myObject.myMethod(1)是一样的

运算符(也即是函数)的名字可以说字母数字,符号。

运算符的优先级由第一个字符决定,运算符优先级递增的顺序如下:

(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)
运算符的结合性由最后一个字符决定: 如果以:结尾的右结合,左结合的则不同

注意赋值运算符的最低的优先级。参考Scala编程语言规范2.9, 6.12.6, 6.12.5可以得到更多信息。

类的层次

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 定义
<span style="white-space:pre">	</span>//一个单例对象,不可以创建另外的实例。

使用Scala创建一个可运行的应用

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

或者

object Hello extends App {
  println("Hello World")
}

类的组织;

  • Classes and objects are organized in packages (package myPackage).
  • 类和对象使用包进行组织
  • They can be referenced through import statements (import myPackage.MyClass, import myPackage._, import myPackage.{MyClass1, MyClass2}, import myPackage.{MyClass1 => A})
  • 他们可以使用import语句进行引用,(import myPackage.MyClass, import myPackage._, 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)
  • 可以直接在代码中使用完整合法的名字
  • 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 Planar
  • Traits类似Java的接口,除了它们拥有非抽象的成员: trait Planar{...} 类Square带着Planar继承Spape
  • General object hierarchy:
  • 通常的对象层次:

scala.Any base type of all types. Has methods hashCode and toString that can be overridden

-Scala.Any 是所有类型基类的基类。拥有可重写的hashCode和toString方法。

scala.AnyVal base type of all primitive types. (scala.Doublescala.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)

- scala.AnyRef 是所有引用类型的基类(java.lang.Object的别名, java.lang.String.scala.List的超类,所有用户自动的类)

scala.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.

- scala.Null 是任意一个 scala.AnyRedf的子类型(null是类型Null的唯一实例),和scala.Nothing是一个所有其他没有实例的类型的字类型


类型参数

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  这个类型可以推导,
可以限制使用的类型:


def myFct[T <: TopLevel](arg: T): T = { ... } // T must derive from TopLevel or be TopLevel  T必须继承于TopLevel
<span style="white-space:pre">	</span>//或者必须是TopLevel
def myFct[T >: Level1](arg: T): T = { ... }   // T must be a supertype of Level1  T必须是Level1的超类型
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

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.

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


模式匹配

模式匹配是用来分解数据结构的

unknownObject match {
  case MyClass(n) => ...
  case MyClass2(a, b) => ...
}
几个例子:

(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,
                           // xs to the tail. xs could be Nil or some other list.
  case 1 :: 2 :: cs => ... // lists that starts with 1 and then 2
  case (x, y) :: ps => ... // a list where the head element is a pair
  case _ => ...            // default case if none of the above matches
}


集合类

Scala定义了一些集合类:

Base Classes

基类:
  • Iterable(可迭代的)
  • Seq(有序序列)
  • Set
  • Map (用于查找数据结构)

Immutable Collections

不可变集合
  • List(链表,提供快速序列的访问)
  • Stream(和List一样,除了tail只在需要的时候会被计算)
  • Vector(类似array的类型,作为tree of blocks来实现,提供快速随机访问。
  • Range(间隔相等的有序整数序列, 即等差数列)
  • String(Java 类型,隐式地转换到字符序列,所以你可以把每个string当做一个Seq[Char]
  • Map(将键映射到值的集合)
  • Set(没有重复元素的集合)
可变的集合
  • Array(Scala集合是JVM原生的运行时数组,因而效率很高
  • Scala有可变的map和set, 可变的类型只在当使用不可变类型是有效率问题是才使用
例子:
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)), 不是O(1) !!!,因为是用tree of blocks实现的
<span style="white-space:pre">	</span>数组
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),( 不是O(1),难道是新生成一个链表么)
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, 满足条件p的最长包含元素的前缀
xs dropWhile p    // the remainder of the list after any leading element satisfying p have been removed,(满足p前缀去除之后的序列)
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
</pre>Pair(类似更大的元组:<p></p><pre code_snippet_id="1786674" snippet_file_name="blog_20160727_26_7737723" name="code" class="java">val pair = ("answer", 42)   // type: (String, Int)
val (label, value) = pair   // label = "answer", value = 42  
pair._1 // "answer"  
pair._2 // 42 


Ordering

在标准库里已经存在一个表示顺序的类: scala.math.Ordering[T],包含比较函数,比如给标准类型的lt()和gt(),带单一自然顺序的类型都应该从trait scala.math.Ordered[T]继承。

import math.Ordering  

def msort[T](xs: List[T])(implicit ord: Ordering) = { ...}  
msort(fruits)(Ordering.String)  
msort(fruits)   // the compiler figures out the right ordering  

等同于
(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 (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.





本博文英文版参考

 https://github.com/lampepfl/progfun-wiki/blob/gh-pages/CheatSheet.md

https://www.coursera.org/learn/progfun1/supplement/Sauv3/cheat-sheet





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值