The set of functions does not allow update value in place, only a collection of function operations, and each operation produces a new collection. Does this cause a lot of copy? It's amazing, No!
Implement list yourself
The role of package ch3.dslistsealed trait list[+a] //sealed: all inherited List types must be defined in this file case object nil extends list[nothing]case class cons[+a] (head: A, tail: list[a]) extends List[A]object List { // sum function def SUM (Ints: list[int]): int = ints match { case Nil => 0 case cons (X, XS) => x + sum (XS) // using a constructor for pattern matching } // quadrature functions, requiring that one of the 0 returns 0 immediately def product (nums: list[double]) : Double = nums match { case nil => 1.0 case cons (0.0, XS) = > 0 case cons (X, XS) => x * product (XS) } // How to create a List def apply[a] (as: a*):list[a] = { if (As.isempty) nil else cons (as.head, apply (as.tail: _* )) }}
Test
Package ch3.dslistobject testlist { println ("Welcome to the scala worksheet ") //> welcome to the scala worksheet val example = cons (1, cons (2, cons (3, Nil)) //> example : ch3.dslist.cons[int] = cons (1,Cons (2,Cons (3, Nil)) val example2 = list (1.0, 2.0, 3.0) //> example2 : ch3.dslist.list[ Double] = cons (1.0,cons (2.0,cons (3.0,nil))) list.sum (example) //> res0: Int = 6 List.product (example2) //> res1: double = 6.0}
2. Add a common operation
def tail[a] (L: list[a]): list[a] = l match { case nil => throw new error ("Nil.tail") Case cons (X, XS) => xs } def drop[A] (l: list[a], n: int): list[a] = { if (n == 1) tail (L) else drop (tail (L), n-1) } def dropwhile[a] (L: list[a]) (F: a => boolean): list[a] = l match { case nil => nil case cons (x,  XS) => if (f (x)) dropwhile (XS) (f) else cons (X, dropwhile (XS) (f)) } def Sethead[a] (L: liSt[a], h: a): list[a] = cons (h, l) // o (N) def append[a] (A1: list[a], a2: list[a]): list[a] = a1 match { case nil => a2 case cons (x, XS) => cons (X, append (XS, A2)) }
These operations do not have a lot of copy, but they reuse the memory. Because the whole is immutable, all the parts are also immutable. When call tail, just return the tail reference. Do not worry about the future because the original list has changed, and affect the list as the return value.
The world should have immutable and muttable coexist. Because some operations are more efficient at immutable collections, such as Tail,append. Some operations are more efficient in muttable collections, such as update an element
3. Implement the INIT function to return the list of elements in order, except for the last element
def Init[a] (L:list[a]): list[a] = l Match {case Nil + nil case Cons (x, xs) + XS Match {case Nil = List () case Cons (y, ys) = Cons (x, init (xs))}}
4. Implement the Foldright function. Use it to improve sum and product
def Foldright[a, b] (L:list[a], z:b) (f: (A, B) and b): B = L Match {case Nil ~ = Z Case Cons (x, xs) = f (x, Foldright (XS, z) (f))} def sum2 (l:list[int]) = Foldright (l, 0) (_ + _) def product2 (l:list[double]) = Foldright (l , 1.0) (_ * _)
5. Implement the length function with Foldright
def Length[a] (L:list[a]): Int = foldright (l, 0) ((A, b) + = B + 1)
6. The implementation of our Foldright function is not recursive, and when the list is large it is easy to cause stackoverflow. Now implement a foldleft function with tail recursion and re-implement sum and product.
def Foldleft[a, b] (L:list[a], z:b) (f: (A, B) and b): b = {def FF = 0 def loop (a:b, M:list[a]): b = m match {Case Nil and a case Cons (x, xs) and Loop (f (x, a), XS)} loop (Z, L)} def sum3 (l:list[int]) = f OldLeft (l, 0) (_ + _) def product3 (l:list[double]) = Foldleft (L, 1.0) (_ * _)
The general method of changing non-tail recursion to tail recursion is to re-implement the algorithm with cyclic structure and write the cyclic structure into a new recursive
7.Write a function that transforms a list of integers by adding 1 to each element. (Reminder:this should is a pure function that returns a new!) List
Add 1 to each element
def addone (L:list[int]): list[int] = l Match {case Nil + nil case Cons (x, xs) = Cons (x +1, AddOne (XS))}
8. Write a function that turns each value in a list[double] into a. String
Converts a double to a string
def all2string (l:list[double]): list[string] = l Match {case Nil + nil case Cons (x, xs) = Cons (x.tostring, All2string (XS))}
9. Implementing the Map function
def Map[a, b] (L:list[a]) (f:a = b): list[b] = l Match {case Nil = nil case Cons (x, xs) = Cons (f (x), MA P (XS) (f))}
Write a function that removes elements from a list filter unless they satisfy a given predicate. Use it to remote all odd numbers from a. List[int]
Implement the filter function and use it to sift through all the odd numbers in List[int]
def Filter[a] (L:list[a]) (f:a = Boolean): list[a] = l Match {case Nil + nil case Cons (x, xs) = if (f (x)) Cons (x, Filter (XS) (f)) Else filter (XS) (f)}
11. Implement Flatmap
def Flatmap[a, B] (L:list[a]) (f:a = List[b]): list[b] = l Match {case Nil + nil case Cons (x, xs) = F (x) match {case Nil = FlatMap (xs) (f) Case Cons (y, ys) = Append (f (x), FlatMap (XS) (f))}}
12. Using Flatmap to implement filter
def Filter2[a] (L:list[a]) (f:a = Boolean): list[a] = FlatMap (l) (x = if (f (x)) List (x) Else Nil)
13. Implementing Vector Addition
Example: Add (List (all), List (2, 3, 4) = List (3, 5, 7)
def Head[a] (L:list[a]): A = l Match {case Nil + = throw new Error ("Nil.head") Case Cons (x, xs) = x} def Add (A1:list[int], A2:list[int]): list[int] = A1 Match {case Nil = nil case Cons (x, xs) = Cons (x + Head (a 2), add (xs, tail (A2)))}
14. Determine if a sequence is a sub-sequence of another sequence: Def Hassubsequence[a] (L:list[a], Sub:list[a]): Boolean
We use the most natural algorithm to judge: Take the second list and the first list from the beginning of the comparison, if not equal, starting from the second element to compare.
The algorithm obviously relies on two other functions: 1. equals function, used to compare two List 2. Take function to get the first n elements
def take[a] (l: list[a], n: int): list[a] = l match { case Nil => if (n == 0) nil else throw new exception ("No element" ) case cons (X,&NBSP;XS) => if (n >= 1) cons (X, take (xs, n-1)) else nil } def equals[a] (A: list[a], b: list[a]): Boolean = a match { case Nil => b match { case Nil => true case _ => false } &nbsP; case cons (X,&NBSP;XS) => b match { case Nil => false case cons (Y, ys) => if (x == y) equals (Xs, ys) else false } } def hassubsequence[a] (A: list[a], b: list[a]): boolean = { if (Length (a) < length (b)) false else { val c = take (A, length (b)) if (Equals (c, b)) true else Hassubsequence (Tail (a), b) &NBSP;&NBSP;&NBsp; } }
Obviously, the above code can be optimized in many places, such as the length function and the Take function, which is a waste of time.
Implementation of the Play Scala 4 list