zoukankan      html  css  js  c++  java
  • Scala 函数式程序设计原理(5)--Lists

    5.1 More Functions on Lists

    xs.length  The number of elements of xs

    xs.last    The List's last element, exception if xs is empty

    xs.init    A list consisting of all elements of xs except the last one, exception if xs is empty

    xs take n  A list consisting of the first n elements of xs, or xs itself it is shorter than n

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

    xs(n)    (or, written out, xs apply n). The element of xs at index n.

    Creating new lists:

    xs ++ ys      The list consisting of all elements of xs followed by all elements of ys

    xs.reverse      The list containing the elements of xs in reversed order

    xs updated (n, x)  The list containing the same elements as xs, except at index n where it contains x.

    Finding elements:

    xs indexOf x    The index of the first element in xs equal to x, or -1 if x does not appear in xs

    xs contains x    same as xs indexOf x >= 0

    5.2 Pairs and Tuples

    A tuple type (t1, ..., tn) is an abbreviation of the parameterized type scala.Tuplen[t1, ..., tn]

    A tuple expression (e1, ..., en) is equivalent to the function application scala.Tuplen(e1, ..., en)

    5.3 Implicit Parameters

    scala.math.Ordering[T] : a class in the standard library that represents orderings.

    Rules for Implicit Parameters:

    Say, a function takes an implicit parameter of type T.

    The compiler will search an implicit definition that

    • is marked implicit
    • has a type compatible with T
    • is visible at the point of the function call, or is defined in a companion object associated with T.

    5.4 Higher-Order List Functions

    Map:

    This scheme can be generalized to the method map of the List class.

    A simple way to define map is as follows:

    abstract class List[T] { ...
      def map[U](f: T => U): List[U] = this match {
        case Nil    => this
        case x :: xs  => f(x) :: xs.map(f)
      }
    }

    Filter:

    This pattern is generalized by the method filter of the List class:

    abstract class List[T] {
      ...
      def filter(p: T => Boolean): List[T] = this match {
        case Nil    => this
        case x :: xs  => if(p(x)) x :: xs.filter(p) else xs.filter(p)
      }
    }

     Using filter, posElems can be writtern more concisely.

    def posElems(xs: List[Int]): List[Int] =
      xs filter (x => x > 0)

     other higher order functions:

    object listfun {
      val nums = List(2, -4, 5, 7, 1)                 //> nums  : List[Int] = List(2, -4, 5, 7, 1)
      val fruits = List("apple", "pineapple", "orange", "banana")
                                                      //> fruits  : List[String] = List(apple, pineapple, orange, banana)
      
      nums filter (x => x > 0)                        //> res0: List[Int] = List(2, 5, 7, 1)
    	nums filterNot (x => x > 0)               //> res1: List[Int] = List(-4)
    	nums partition (x => x > 0)               //> res2: (List[Int], List[Int]) = (List(2, 5, 7, 1),List(-4))
    	nums takeWhile (x => x > 0)               //> res3: List[Int] = List(2)
    	nums dropWhile (x => x > 0)               //> res4: List[Int] = List(-4, 5, 7, 1)
    	nums span (x => x > 0)                    //> res5: (List[Int], List[Int]) = (List(2),List(-4, 5, 7, 1))
    
    }
    

    5.5 Reduction of Lists

    reduceLeft:

    def sum(xs: List[Int])    = (0::xs) reduceLeft (_ + _)
    def product(xs: List[Int])  = (1::xs) reduceRight (_ * _)

    foldLeft:

    foldLeft is like reduceLeft but takes an accumulator, z, as an additional parameter, which is returned when foldLeft is called on an empty list.

    (List(x1, ..., xn) foldLeft z)(op) = (...(z io x1) op ... ) op xn
    

     so sum and product can also be defined as follows:

    def sum(xs: List[Int])     = (xs foldLeft 0) (_ + _)
    def product(xs: List[Int])  = (xs foldLeft 1) (_ * _) 

     implementation:

    abstract class List[T] { ...
      def reduceLeft(op: (T, T) => T):T = this match {
        case Nil => throw new Error("Nil.reduceLeft")
        case x::xs => (xs foldLeft x)(op)
      }

      def foldLeft[U](z: U)(op: (U, T) => U): U = this match {
        case Nil => z
        case x:: xs => (xs foldLeft op(z, x))(op)
      }
    }

    FoldRight and ReduceRight:

    Applications of foldLeft and reduceLeft unfold on trees that lean to the left.

    They have two dual functions, foldRight and reduceRight, which produce trees which lean to the right, i.e.,

    List(x1, ..., x{n-1}, xn) reduceRight op = x1 op ( ... (x{n-1} op xn) ... )
    (List(x1, ..., xn) foldRight acc)(op) = x1 op ( ... (xn op acc) ... )

    implementation:

    def reduceRight(op: (T, T) => T): T = this match {
      case Nil => throw new Error("Nil.reduceRight")
      case x :: Nil => x
      case x :: xs => op(x, xs.reduceRight(op))
    }
    def foldRight[U](z: U)(op: (T, U) => U): U = this match {
      case Nil => z
      case x::xs => op(x, (xs foldRight z)(op))
    }

    Difference between FoldLeft and FoldRight:

    For operators that are associative and commutative, foldLeft and foldRight are equivalent (even though there may be a difference in efficiency)

    But sometimes, only one of the two operators is appropriate.

    implemention of mapFun and lengthFun using foldRight:

    	def mapFun[T, U] (xs: List[T], f: T=> U): List[U] = (xs foldRight List[U]())(f(_) :: _)
                                                      //> mapFun: [T, U](xs: List[T], f: T => U)List[U]
    	mapFun[Int, Int](nums, x => x + 1)        //> res7: List[Int] = List(3, -3, 6, 8, 2)
    	
    	def lengthFun[T](xs: List[T]): Int = (xs foldRight 0) ((_,acc) => acc+1)
                                                      //> lengthFun: [T](xs: List[T])Int
    	lengthFun(nums)                           //> res8: Int = 5
    

    5.6 Reasoning About Concat

    Structual induction:

    To prove a property P(xs) for all lists xs,

    • show that P(Nil) holds (base case),
    • for a list xs and some element x, show the induction step:  if P(xs) holds, then P(x::xs) also holds.
  • 相关阅读:
    MAC配置DNS服务器
    真机IOS8.3以上的文件夹共享
    appium + python的环境配置_windows
    python 的时间与日期
    sublimetext 2 编译文件带input时 提示 EOFError: EOF when reading a line
    cmd无法输入中文解决方案
    配置python学习环境遇到的问题:[Decode error
    monkey初接触
    Android logcat输出中文乱码
    运行 命令框不记录打过的命令,重启后CMD里面是空的.上次打过的命令消失了.
  • 原文地址:https://www.cnblogs.com/PaulingZhou/p/6900143.html
Copyright © 2011-2022 走看看