scala读书学习笔记008

1、列表是不可变的。也就是说,列表的元素不能通过赋值改变。其次,列表的结构是递归的(即链表,linked list),而数组是平的。

2、List类型跟数组一样,列表也是同构(homogeneous)的:同一个列表的所有元素都必须是相同的类型。元素类型为T的列表的类型写作List[T],Scala的列表类型是协变(covariant)的。意思是对每一组类型S和T,如果S是T的子类型,那么List[S]就是List[T]的子类型。List[String]是List[Object]的子类型。因为每个字符串列表也都可以被当作对象列表,在Scala的类继承关系中,Nothing是底类型。由于列表是协变的,对于任何T而言,List[Nothing]都是List[T]的子类型。因此,既然空列表对象的类型为List[Nothing],可以被当作其他形如List[T]类型的对象。

3、所有的列表都构建自两个基础的构建单元:Nil和::(读作“cons”)。Nil表示空列表。中缀操作符::表示在列表前追加元素。也就是说,x :: xs表示这样一个列表:第一个元素为x,接下来是列表xs的全部元素。由于::以冒号结尾,::这个操作符是右结合的,:A :: B :: C会被翻译成 A :: (B :: C)。因此,我们可以在前面的定义中去掉圆括号。head和tail方法只对非空列表有定义。当我们从一个空列表调用时,它们将抛出异常。对一个空列表排序交出空列表。

4、列表也可以用模式匹配解开。列表模式可以逐一对应到列表表达式。我们既可以用List(...)这样的模式来匹配列表的所有元素,也可以用::操作符和Nil常量一点点地将列表解开。

5、List(a, b, c)这个模式匹配长度为3的列表,并将三个元素分别绑定到模式变量a、b和c。如果我们事先并不知道列表中元素的个数,更好的做法是用::来匹配。

6、cons”模式是中缀操作模式的一个特例。作为表达式,中缀操作等同于一次方法调用。对模式而言,规则是不同的:作为模式,p op q这样的中缀操作等同于op(p, q)。也就是说,中缀操作符op是被当作构造方法模式处理的。具体来说,x :: xs这个表达式相当于::(x, xs)。一个名为::的类与这个模式构造方法相对应。的确有这么一个类,它的名字叫scala.::,并且就是用来构建非空列表的。因此::在Scala中出现了两次,一次是作为scala包中的一个类的名字,一次是在List类的方法名。::方法的作用是产出一个scala.::类的实例。

7、如果一个方法不接收任何函数作为入参,就被称为初阶(first-order)方法。

8、拼接两个列表
跟::操作相似的一个操作是拼接,写作:::。不同于::,:::接收两个列表参数作为操作元。xs ::: ys的结果是一个包含了xs所有元素,加上ys所有元素的新列表,跟cons类似,列表的拼接操作也是右结合的。

9、对于列表这样的递归数据结构的“分而治之”的程序设计原则。许多对列表的算法都首先会用模式匹配将输入的列表切分成更小的样例。这是设计原则中“分”的部分。然后对每个样例构建对应的结果。如果结果是一个非空的列表,那么这个列表的局部可以通过递归地调用同一个算法来构建出来。这是设计原则中“治”的部分。

10、不同于数组,在列表上的length操作相对更耗资源。找到一个列表的末尾需要遍历整个列表,因此需要消耗与元素数量成正比的时间。这也是为什么将xs.isEmpty这样的测试换成xs.length == 0并不是个好的主意。这两种测试的结果并没有区别,但第二个会更慢,尤其当列表xs很长时。

11、我们已经知道基本的操作head和tail,它们分别获取列表的首个元素和除了首个元素剩余的部分。它们也分别有一个对偶(dual)方法:last返回(非空)列表的最后一个元素,而init返回除最后一个元素之外剩余的部分,跟head和tail一样,这两个方法在应用到空列表的时候也会抛出异常。

12、drop和take是对tail和init的一般化。怎么说呢?它们返回的是列表任意长度的前缀或后缀。表达式“xs take n”返回列表xs的前n个元素。如果n大于xs.length,那么将返回整个xs列表。操作“xs drop n”返回列表xs除前n个元素之外的所有元素。如果n大于等于xs.length,那么就返回空列表。

13、flatten方法接收一个列表的列表并将它扁平化,返回单个列表。

14、拉链(zip)操作接收两个列表,返回一个由对偶组成的列表,如果两个列表的长度不同,那么任何没有配对上的元素将被丢弃。一个有用的特例是将列表和它的下标zip起来。最高效的做法是用zipWithIndex方法,这个方法会将列表中的每个元素和它出现在列表中的位置组合成对偶。任何元组的列表也可以通过unzip方法转换回由列表组成的元组。

15、toString操作返回列表的标准字符串表现形式,如果需要不同的表现形式,可以用mkString方法。xs mkString (pre, sep, post)涉及四个操作元:要显示的列表xs、出现在最前面的前缀字符串pre、在元素间显示的分隔字符串sep,以及出现在最后面的后缀字符串post。

16、mkString和addString这两个方法继承自List的超特质Traversable,因此它们也可以用在所有其他集合类型上。

17、为了在扁平的数组世界和递归的列表世界之间做数据转换,可以使用List类的toArray和Array类的toList方法。

18、xs map f这个操作将类型为List[T]的列表xs和类型为T => U的函数f作为操作元。它返回一个通过应用f到xs的每个元素后得到的列表。map返回的是列表的列表,而flatMap返回的是所有元素拼接起来的单个列表。oreach要求右操作元是一个过程(结果类型为Unit的函数)。它只是简单地将过程应用到列表中的每个元素。整个操作本身的结果类型也是Unit,并没有列表类型的结果被组装出来。

19、“xs filter p”这个操作的两个操作元分别是类型为List[T]的xs和类型为T => Boolean的前提条件函数p。partition方法跟filter很像不过返回的是一对列表。其中一个包含所有前提条件为true的元素,另一个包含所有前提条件为false的元素。find方法跟filter也很像,不过它返回满足给定前提条件的第一个元素,而不是所有元素。xs find p这个操作接收列表xs和前提条件函数p两个操作元,返回一个可选值。如果xs中存在一个元素x满足p(x)为true,那么就返回Some(x)。而如果对于所有元素而言p都为false,那么则返回None。

19、takeWhile和dropWhile操作符也将一个前提条件作为右操作元。xs takeWhile p操作返回列表xs中连续满足p的最长前缀。同理,xs dropWhile p操作将去除列表xs中连续满足p的最长前缀。
span方法将takeWhile和dropWhile两个操作合二为一,就像splitAt将take和drop合二为一一样。xs forall p这个操作接收一个列表xs和一个前提条件p作为入参。如果列表中所有元素都满足p就返回true。与此相反,xs exists p操作返回true的要求是xs中存在一个元素满足前提条件p。xs.foldLeft(z)(op)操作涉及三个对象:起始值z、列表xs和二元操作op。折叠的结果是以z为前缀,对列表的元素依次连续应用op。foldLeft操作产生一棵往左靠的操作树。与之相仿,还有另一个foldRight操作,产生一棵往右靠的操作树。

20、flattenLeft,由于列表拼接xs ::: ys的执行时间跟首个入参xs的长度成正比,用右折叠的flattenRight比用左折叠的flattenLeft更高效。左折叠在这里的问题是flattenLeft(xss)需要复制首个元素列表xss.headn-1次,其中n为列表xss的长度。

21、操作(List(), x)等同于List(x),而List(x)也可以写作x :: List()。

22、通过zip方法操作多个列表的一个弊端是这个过程(zip调用)将创建一个中间列表,如果列表的元素较多,会有较大的开销。lazyZip和zip的区别是lazyZip不会立即返回一个集合(因此我们叫它“lazy”),而是返回一个提供了对zip在一起的列表进行各项操作(包括map操作)的值。

23、一般来说,当类型推断算法需要推断一个多态方法的类型参数时,它会考虑第一个参数列表里的所有入参的类型,但到此为止。由于msortSwapped是一个柯里化的方法,它有两个参数列表,第二个入参(即函数值)并不会用来判定方法的类型参数。这样的类型推断机制引导出如下的类库设计原则:当我们设计一个接收某些非函数的入参和一个函数入参时,将函数入参单独放在最后一个参数列表中。这样一来,方法的正确实例类型可以从那些非函数入参推断出来,而这个类型又能被继续用于对函数入参做类型检查。这样做的净收益是方法的使用者需要给出的类型信息更少,因而在编写函数字面量时可以更精简。

24、当我们对多态方法相关的错误提示感到困惑时,添加类型注解也是一个有用的调试技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值