Scala cheetsheet,小抄,语法整理

来源:互联网 发布:冠道车钥匙淘宝图片 编辑:程序博客网 时间:2024/06/05 17:29


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 thissum((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>//或者必须是TopLeveldef myFct[T >: Level1](arg: T): T = { ... }   // T must be a supertype of Level1  T必须是Level1的超类型def myFct[T >: Level1 <: Top Level](arg: T): T = { ... }


VarianceGiven A <: BIf C[A] <: C[B], C is covariantIf C[A] >: C[B], C is contravariantOtherwise C is nonvariant

class C[+A] { ... } // C is covariantclass C[-A] { ... } // C is contravariantclass 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 listsval fruit = "apples" :: ("oranges" :: ("pears" :: Nil)) // parens optional, :: is right-associativefruit.head   // "apples"fruit.tail   // List("oranges", "pears")val empty = List()val empty = Nilval 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 bananaval r: Range = 1 until 5 // 1, 2, 3, 4val s: Range = 1 to 5    // 1, 2, 3, 4, 51 to 10 by 3  // 1, 4, 7, 106 to 1 by -2  // 6, 4, 2val s = (1 to 6).toSets map (_ + 2) // adds 2 to each element of the setval s = "Hello World"s filter (c => c.isUpper) // returns "HW"; strings can be treated as Seq[Char]// Operations on sequencesval 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 xsxs drop n   // the rest of the collection after taking n elementsxs(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 >= 0xs filter p       // returns a list of the elements that satisfy the predicate pxs 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 xnList(x1, ..., xn).foldLeft(z)(op)  // (...( z op x1) op x2) op ...) op xnList(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 truexs forall p    // true if p(x) is true for all elementsxs zip ys      // returns a list of pairs which groups elements with same index togetherxs unzip       // opposite of zip: returns a pair of two listsxs.flatMap f   // applies the function to all elements and concatenates the resultxs.sum         // sum of elements of the numeric collectionxs.product     // product of elements of the numeric collectionxs.max         // maximum of collectionxs.min         // minimum of collectionxs.flatten     // flattens a collection of collection into a single-level collectionxs groupBy f   // returns a map which points to a list of elementsxs distinct    // sequence of distinct entries (removes duplicates)x +: xs  // creates a new collection with leading element xxs :+ x  // creates a new collection with trailing element x// Operations on mapsval myMap = Map("I" -> 1, "V" -> 5, "X" -> 10)  // create a mapmyMap("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 Streamsval 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 RulesA for-expression looks like a traditional for loop but works differently internallyfor (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 e2for (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 0
原创粉丝点击