Scala 中的函数式编程基础(三)

时间:2021-11-17 09:21:50

主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 《Functional Programming Principles in Scala》


3. Data and Abstraction

3.1 Class Hierarchies

这一集字幕不同步-,-,听得有点费力!

类的概念和其他语言里面很相似,基类,子类,父类啥的叫法差不多。在 Scala 中,所有用户自定义的类都是另外一个类的子类,如果没有显式给定父类,java 里面默认继承 java.lang,scala 里面是 Object。无论基类中的方法有没有具体实现,子类都可以用 override 重新定义,回想起之前强大的 toString 了吗?

举一个二叉树的例子:

package week3

object insets {
val t1 = new NonEmpty(, Empty, Empty) //> t1 : week3.NonEmpty = {.3.}
val t2 = t1 incl //> t2 : week3.IntSet = {.3{.4.}}
val t3 = new NonEmpty(, Empty, Empty) //> t3 : week3.NonEmpty = {.5.}
t2 union t3 //> res0: week3.IntSet = {{{.3.}4.}5.}
} abstract class IntSet { // 抽象类作为基类,无法实例化,定义了三个接口
def contains(x: Int): Boolean // 查找是否包含 x
def incl(x: Int): IntSet // 如果 x 不存在,将 x 放入二叉树中
def union(x: IntSet): IntSet // 两棵树融合
} object Empty extends IntSet { // Empty 是 IntSet 的 subclass,`object` 表示单例模式,所有空节点都可以用一个对象来表示
def contains(x: Int): Boolean = false
def incl(x: Int): IntSet = new NonEmpty(x, Empty, Empty)
def union(other: IntSet): IntSet = other
override def toString = "." // 空节点打印"."
} class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet {
def contains(x: Int): Boolean =
if (x < elem) left contains x
else if (x > elem) right contains x
else true def incl(x: Int): IntSet =
// 实际上创建了一个新树,新树和旧树共用未改变的子树
// 这个叫 persistent data structure,是把函数式编程扩展到 collections 的关键之一
// 反正他是这么说的 `-,-`
if (x < elem) new NonEmpty(elem, left incl x, right) // 一重一重地复制节点
else if (x > elem) new NonEmpty(elem, left, right incl x)
else this def union(other: IntSet): IntSet =
((left union right) union other) incl elem // override def toString = "{" + left + elem + right + "}" //强大的递归啊
}

3.2 How Classes Are Organized

没学过 java,估计和 java 中 package 管理一样。

在源码最顶端写上 package week3 表示这个文件的 object 或者 class 属于这个包。要使用某一个类,可以在源码中用全名 week3.classA,也可以像 python 一样在最开始 import,源码中间用类名:

  • import week3.classA:导入类 classA
  • import week3.{classA, classB}:导入两个类
  • import week3._ :导入包所有(通配符导入方法)

除了从包导入,还可以从 object 导入。所有 Scala 程序默认导入一些 entities,比如 scala 中的 Int,java.lang 中的 Object,scala.Predef 中的断言等。更多信息可以查看 scala 的标准库

在 java 和 scala 中,一个类只能有一个父类(单继承),如何实现多继承,scala 中采用 traits。trait 像 java 里面的接口,偏抽象,但是更强大,可以包含 field 和具体方法,但是不能有value参数。子类可只能继承一个父类,但是可以继承任意多个 traits,例如:class Square extends Shape with Planar with Moveble

scala 类型结构如下,实线表示继承,虚线表示隐式转化。

  • Any是所有类型的基本类,包含的方法有:‘==’,‘!=’,‘equals’,‘hashCode’,‘toString’
  • AnyVal是数值类型的基本类。
  • AnyRef是所有引用类型的基本类,也是 java.lang.Object 的别名。
  • Nothing是所有类的子类型。主要作用是异常类与collection中的一个空元素。
  • Null 是所有类的子类型。但是与 AnyVal 的子类型不兼容。

Scala 中的函数式编程基础(三)

Q:if (true) 1 else False 的返回类型是什么?
A:int 和 boolean 类型,返回父类 AnyVal。

3.3 Polymorphism

Polymorphism 意味着函数可以以多种类型出现。一张 PPT 总结 Polymorphism:

Scala 中的函数式编程基础(三)

假设我们要建立一个 list 类,它可能包含了不同的数据类型(整数,布尔,list自身类型等),例子如下:

Scala 中的函数式编程基础(三)

这时需要用泛型来表示。新建一个package叫week4,在其中新建一个 trait。它的两个‘子类’分别为 Cons 和 Nil,分别表示含有元素的节点和空节点。

package week4

// [T] 是类型参数,比如int,double之类。是泛型编程的基础
trait List[T] {
def isEmpty: Boolean
def head: T
def tail: List[T]
} class Cons[T](val head: T, val tail: List[T]) extends List[T] {
def isEmpty = false
// head 和 tail 已经在初始化中实现
} class Nil[T] extends List[T] {
def isEmpty = true
def head: Nothing = throw new NoSuchElementException("Nil.head")
// Nothing 是任何类型的子类,所以也是 T 的子类
def tail: Nothing = throw new NoSuchElementException("Nil.tail")
}

在 week4 中新建一个 scala worksheet,测试一下上述代码:

package week4

import week4._

object nth {
// 创建一个含有一个元素的 list
def singleton[T](elem: T) = new Cons(elem, new Nil)
//> singleton: [T](elem: T)week4.Cons[T]
singleton[Int](3) //> res0: week4.Cons[Int] = week4.Cons@71be98f5
singleton(3) // 编译器可以从 3 推到出 T 是 Int // 寻找 list 中的第 n 个元素
def nth[T](n: Int, xs: List[T]): T =
if (xs.isEmpty) throw new IndexOutOfBoundsException
else if (n == 0) xs.head
else nth(n - 1, xs.tail) //> nth: [T](n: Int, xs: week4.List[T])T // 创建一个 list = [1, 2, 3]
val list = new Cons(1, new Cons(2, new Cons(3, new Nil)))
nth(2, list) //> res2: Int = 3
}

小记

这里是课程前四次的大概内容,因为第一次课是教你怎么安装,所以实际内容只有三次课,后面还有四次课。总体来说,函数式编程给人很多启发,但是如果不是真正需要用,也不宜占用太多时间去学习。暑假要去实习了,等下学期再学吧。

Scala%20%u4E2D%u7684%u51FD%u6570%u5F0F%u7F16%u7A0B%u57FA%u7840%28%u4E09%29%0A%3D%3D%3D%0A%0A@%28scala%29%5B%u5B66%u4E60%u7B14%u8BB0%7CCoursera%5D%0A%0A%3E%20%u4E3B%u8981%u6765%u81EA%20Scala%20%u8BED%u8A00%u53D1%u660E%u4EBA%20Martin%20Odersky%20%u6559%u6388%u7684%20Coursera%20%u8BFE%u7A0B%20**%u300AFunctional%20Programming%20Principles%20in%20Scala%u300B**%u3002%0A%0A---%0A%0A%23%23%203.%20Data%20and%20Abstraction%0A%23%23%23%203.1%20Class%20Hierarchies%0A%u8FD9%u4E00%u96C6%u5B57%u5E55%u4E0D%u540C%u6B65%60-%2C-%60%uFF0C%u542C%u5F97%u6709%u70B9%u8D39%u529B%uFF01%0A%0A%u7C7B%u7684%u6982%u5FF5%u548C%u5176%u4ED6%u8BED%u8A00%u91CC%u9762%u5F88%u76F8%u4F3C%uFF0C%u57FA%u7C7B%uFF0C%u5B50%u7C7B%uFF0C%u7236%u7C7B%u5565%u7684%u53EB%u6CD5%u5DEE%u4E0D%u591A%u3002%u5728%20Scala%20%u4E2D%uFF0C%u6240%u6709%u7528%u6237%u81EA%u5B9A%u4E49%u7684%u7C7B%u90FD%u662F%u53E6%u5916%u4E00%u4E2A%u7C7B%u7684%u5B50%u7C7B%uFF0C%u5982%u679C%u6CA1%u6709%u663E%u5F0F%u7ED9%u5B9A%u7236%u7C7B%uFF0Cjava%20%u91CC%u9762%u9ED8%u8BA4%u7EE7%u627F%20java.lang%uFF0Cscala%20%u91CC%u9762%u662F%20Object%u3002%u65E0%u8BBA%u57FA%u7C7B%u4E2D%u7684%u65B9%u6CD5%u6709%u6CA1%u6709%u5177%u4F53%u5B9E%u73B0%uFF0C%u5B50%u7C7B%u90FD%u53EF%u4EE5%u7528%20%60override%60%20%u91CD%u65B0%u5B9A%u4E49%uFF0C%u56DE%u60F3%u8D77%u4E4B%u524D%u5F3A%u5927%u7684%20%60toString%60%20%u4E86%u5417%uFF1F%0A%0A%u4E3E%u4E00%u4E2A%u4E8C%u53C9%u6811%u7684%u4F8B%u5B50%uFF1A%0A%60%60%60scala%0Apackage%20week3%0A%0Aobject%20insets%20%7B%0A%20%20val%20t1%20%3D%20new%20NonEmpty%283%2C%20Empty%2C%20Empty%29%20%20%20%20%20%20%20%20%20%20//%3E%20t1%20%20%3A%20week3.NonEmpty%20%3D%20%7B.3.%7D%0A%20%20val%20t2%20%3D%20t1%20incl%204%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%3E%20t2%20%20%3A%20week3.IntSet%20%3D%20%7B.3%7B.4.%7D%7D%0A%20%20val%20t3%20%3D%20new%20NonEmpty%285%2C%20Empty%2C%20Empty%29%20%20%20%20%20%20%20%20%20%20//%3E%20t3%20%20%3A%20week3.NonEmpty%20%3D%20%7B.5.%7D%0A%20%20t2%20union%20t3%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%3E%20res0%3A%20week3.IntSet%20%3D%20%7B%7B%7B.3.%7D4.%7D5.%7D%0A%7D%0A%0Aabstract%20class%20IntSet%20%7B%20%20//%20%u62BD%u8C61%u7C7B%u4F5C%u4E3A%u57FA%u7C7B%uFF0C%u65E0%u6CD5%u5B9E%u4F8B%u5316%uFF0C%u5B9A%u4E49%u4E86%u4E09%u4E2A%u63A5%u53E3%0A%20%20def%20contains%28x%3A%20Int%29%3A%20Boolean%20//%20%u67E5%u627E%u662F%u5426%u5305%u542B%20x%0A%20%20def%20incl%28x%3A%20Int%29%3A%20IntSet%20//%20%u5982%u679C%20x%20%u4E0D%u5B58%u5728%uFF0C%u5C06%20x%20%u653E%u5165%u4E8C%u53C9%u6811%u4E2D%0A%20%20def%20union%28x%3A%20IntSet%29%3A%20IntSet%20%20//%20%u4E24%u68F5%u6811%u878D%u5408%0A%20%20%7D%0A%20%20%0Aobject%20Empty%20extends%20IntSet%20%7B%20//%20Empty%20%u662F%20IntSet%20%u7684%20subclass%uFF0C%60object%60%20%u8868%u793A%u5355%u4F8B%u6A21%u5F0F%uFF0C%u6240%u6709%u7A7A%u8282%u70B9%u90FD%u53EF%u4EE5%u7528%u4E00%u4E2A%u5BF9%u8C61%u6765%u8868%u793A%0A%20%20def%20contains%28x%3A%20Int%29%3A%20Boolean%20%3D%20false%0A%20%20def%20incl%28x%3A%20Int%29%3A%20IntSet%20%3D%20new%20NonEmpty%28x%2C%20Empty%2C%20Empty%29%0A%20%20def%20union%28other%3A%20IntSet%29%3A%20IntSet%20%3D%20other%0A%20%20override%20def%20toString%20%3D%20%22.%22%20//%20%u7A7A%u8282%u70B9%u6253%u5370%22.%22%0A%7D%0A%0Aclass%20NonEmpty%28elem%3A%20Int%2C%20left%3A%20IntSet%2C%20right%3A%20IntSet%29%20extends%20IntSet%20%7B%0A%20%20def%20contains%28x%3A%20Int%29%3A%20Boolean%20%3D%0A%20%20%20%20if%20%28x%20%3C%20elem%29%20left%20contains%20x%0A%20%20%20%20else%20if%20%28x%20%3E%20elem%29%20right%20contains%20x%0A%20%20%20%20else%20true%0A%20%20%20%20%0A%20%20def%20incl%28x%3A%20Int%29%3A%20IntSet%20%3D%0A%20%20%20%20//%20%u5B9E%u9645%u4E0A%u521B%u5EFA%u4E86%u4E00%u4E2A%u65B0%u6811%uFF0C%u65B0%u6811%u548C%u65E7%u6811%u5171%u7528%u672A%u6539%u53D8%u7684%u5B50%u6811%0A%20%20%20%20//%20%u8FD9%u4E2A%u53EB%20persistent%20data%20structure%2C%u662F%u628A%u51FD%u6570%u5F0F%u7F16%u7A0B%u6269%u5C55%u5230%20collections%20%u7684%u5173%u952E%u4E4B%u4E00%0A%20%20%20%20//%20%u53CD%u6B63%u4ED6%u662F%u8FD9%u4E48%u8BF4%u7684%20%60-%2C-%60%0A%20%20%20%20if%20%28x%20%3C%20elem%29%20new%20NonEmpty%28elem%2C%20left%20incl%20x%2C%20right%29%20//%20%u4E00%u91CD%u4E00%u91CD%u5730%u590D%u5236%u8282%u70B9%0A%20%20%20%20else%20if%20%28x%20%3E%20elem%29%20new%20NonEmpty%28elem%2C%20left%2C%20right%20incl%20x%29%0A%20%20%20%20else%20this%0A%20%20%20%20%0A%20%20def%20union%28other%3A%20IntSet%29%3A%20IntSet%20%3D%0A%20%20%20%20%28%28left%20union%20right%29%20union%20other%29%20incl%20elem%20%20//%20%0A%20%20%20%20%0A%20%20override%20def%20toString%20%3D%20%22%7B%22%20+%20left%20+%20elem%20+%20right%20+%20%22%7D%22%20//%u5F3A%u5927%u7684%u9012%u5F52%u554A%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%203.2%20How%20Classes%20Are%20Organized%0A%u6CA1%u5B66%u8FC7%20java%uFF0C%u4F30%u8BA1%u548C%20java%20%u4E2D%20package%20%u7BA1%u7406%u4E00%u6837%u3002%0A%0A%u5728%u6E90%u7801%u6700%u9876%u7AEF%u5199%u4E0A%20%60package%20week3%60%20%u8868%u793A%u8FD9%u4E2A%u6587%u4EF6%u7684%20object%20%u6216%u8005%20class%20%u5C5E%u4E8E%u8FD9%u4E2A%u5305%u3002%u8981%u4F7F%u7528%u67D0%u4E00%u4E2A%u7C7B%uFF0C%u53EF%u4EE5%u5728%u6E90%u7801%u4E2D%u7528%u5168%u540D%20%60week3.classA%60%uFF0C%u4E5F%u53EF%u4EE5%u50CF%20python%20%u4E00%u6837%u5728%u6700%u5F00%u59CB%20import%uFF0C%u6E90%u7801%u4E2D%u95F4%u7528%u7C7B%u540D%uFF1A%0A-%20import%20week3.classA%uFF1A%u5BFC%u5165%u7C7B%20classA%0A-%20import%20week3.%7BclassA%2C%20classB%7D%uFF1A%u5BFC%u5165%u4E24%u4E2A%u7C7B%0A-%20import%20week3._%20%uFF1A%u5BFC%u5165%u5305%u6240%u6709%uFF08%u901A%u914D%u7B26%u5BFC%u5165%u65B9%u6CD5%uFF09%0A%0A%u9664%u4E86%u4ECE%u5305%u5BFC%u5165%uFF0C%u8FD8%u53EF%u4EE5%u4ECE%20object%20%u5BFC%u5165%u3002%u6240%u6709%20Scala%20%u7A0B%u5E8F%u9ED8%u8BA4%u5BFC%u5165%u4E00%u4E9B%20entities%uFF0C%u6BD4%u5982%20scala%20%u4E2D%u7684%20Int%uFF0Cjava.lang%20%u4E2D%u7684%20Object%uFF0Cscala.Predef%20%u4E2D%u7684%u65AD%u8A00%u7B49%u3002%u66F4%u591A%u4FE1%u606F%u53EF%u4EE5%u67E5%u770B%20scala%20%u7684%5B%u6807%u51C6%u5E93%5D%28http%3A//www.scala-lang.org/files/archive/api/current/%23package%29%u3002%0A%0A%u5728%20java%20%u548C%20scala%20%u4E2D%uFF0C%u4E00%u4E2A%u7C7B%u53EA%u80FD%u6709%u4E00%u4E2A%u7236%u7C7B%uFF08%u5355%u7EE7%u627F%uFF09%uFF0C%u5982%u4F55%u5B9E%u73B0%u591A%u7EE7%u627F%uFF0Cscala%20%u4E2D%u91C7%u7528%20traits%u3002trait%20%u50CF%20java%20%u91CC%u9762%u7684%u63A5%u53E3%uFF0C%u504F%u62BD%u8C61%uFF0C%u4F46%u662F%u66F4%u5F3A%u5927%uFF0C%u53EF%u4EE5%u5305%u542B%20field%20%u548C%u5177%u4F53%u65B9%u6CD5%uFF0C%u4F46%u662F%u4E0D%u80FD%u6709value%u53C2%u6570%u3002%u5B50%u7C7B%u53EF%u53EA%u80FD%u7EE7%u627F%u4E00%u4E2A%u7236%u7C7B%uFF0C%u4F46%u662F%u53EF%u4EE5%u7EE7%u627F%u4EFB%u610F%u591A%u4E2A%20traits%uFF0C%u4F8B%u5982%uFF1A%60class%20Square%20extends%20Shape%20with%20Planar%20with%20Moveble%60%u3002%0A%0Ascala%20%u7C7B%u578B%u7ED3%u6784%u5982%u4E0B%uFF0C%u5B9E%u7EBF%u8868%u793A%u7EE7%u627F%uFF0C%u865A%u7EBF%u8868%u793A%u9690%u5F0F%u8F6C%u5316%u3002%0A-%20%60Any%60%u662F%u6240%u6709%u7C7B%u578B%u7684%u57FA%u672C%u7C7B%uFF0C%u5305%u542B%u7684%u65B9%u6CD5%u6709%uFF1A%u2018%3D%3D%u2019%uFF0C%u2018%21%3D%u2019%uFF0C%u2018equals%u2019%uFF0C%u2018hashCode%u2019%uFF0C%u2018toString%u2019%0A-%20%60AnyVal%60%u662F%u6570%u503C%u7C7B%u578B%u7684%u57FA%u672C%u7C7B%u3002%0A-%20%60AnyRef%60%u662F%u6240%u6709%u5F15%u7528%u7C7B%u578B%u7684%u57FA%u672C%u7C7B%uFF0C%u4E5F%u662F%20java.lang.Object%20%u7684%u522B%u540D%u3002%0A-%20%60Nothing%60%u662F%u6240%u6709%u7C7B%u7684%u5B50%u7C7B%u578B%u3002%u4E3B%u8981%u4F5C%u7528%u662F%u5F02%u5E38%u7C7B%u4E0Ecollection%u4E2D%u7684%u4E00%u4E2A%u7A7A%u5143%u7D20%u3002%0A-%20%60Null%60%20%u662F%u6240%u6709%u7C7B%u7684%u5B50%u7C7B%u578B%u3002%u4F46%u662F%u4E0E%20AnyVal%20%u7684%u5B50%u7C7B%u578B%u4E0D%u517C%u5BB9%u3002%0A%21%5BAlt%20text%5D%28./classhierarchy.png%29%0A%0A**Q%uFF1A**%60if%20%28true%29%201%20else%20False%60%20%u7684%u8FD4%u56DE%u7C7B%u578B%u662F%u4EC0%u4E48%uFF1F%0A**A%uFF1A**int%20%u548C%20boolean%20%u7C7B%u578B%uFF0C%u8FD4%u56DE%u7236%u7C7B%20AnyVal%u3002%0A%0A%23%23%23%203.3%20Polymorphism%0A%0APolymorphism%20%u610F%u5473%u7740%u51FD%u6570%u53EF%u4EE5%u4EE5%u591A%u79CD%u7C7B%u578B%u51FA%u73B0%u3002%u4E00%u5F20%20PPT%20%u603B%u7ED3%20Polymorphism%uFF1A%0A%21%5BAlt%20text%5D%28./Selection_006.png%29%0A%0A%u5047%u8BBE%u6211%u4EEC%u8981%u5EFA%u7ACB%u4E00%u4E2A%20list%20%u7C7B%uFF0C%u5B83%u53EF%u80FD%u5305%u542B%u4E86%u4E0D%u540C%u7684%u6570%u636E%u7C7B%u578B%uFF08%u6574%u6570%uFF0C%u5E03%u5C14%uFF0Clist%u81EA%u8EAB%u7C7B%u578B%u7B49%uFF09%uFF0C%u4F8B%u5B50%u5982%u4E0B%uFF1A%0A%21%5BAlt%20text%5D%28./Selection_005.png%29%0A%0A%u8FD9%u65F6%u9700%u8981%u7528%u6CDB%u578B%u6765%u8868%u793A%u3002%u65B0%u5EFA%u4E00%u4E2Apackage%u53EBweek4%2C%u5728%u5176%u4E2D%u65B0%u5EFA%u4E00%u4E2A%20trait%u3002%u5B83%u7684%u4E24%u4E2A%u2018%u5B50%u7C7B%u2019%u5206%u522B%u4E3A%20Cons%20%u548C%20Nil%uFF0C%u5206%u522B%u8868%u793A%u542B%u6709%u5143%u7D20%u7684%u8282%u70B9%u548C%u7A7A%u8282%u70B9%u3002%0A%60%60%60scala%0Apackage%20week4%0A%0A//%20%5BT%5D%20%u662F%u7C7B%u578B%u53C2%u6570%uFF0C%u6BD4%u5982int%uFF0Cdouble%u4E4B%u7C7B%u3002%u662F%u6CDB%u578B%u7F16%u7A0B%u7684%u57FA%u7840%0Atrait%20List%5BT%5D%20%7B%0A%20%20def%20isEmpty%3A%20Boolean%0A%20%20def%20head%3A%20T%0A%20%20def%20tail%3A%20List%5BT%5D%0A%7D%0A%0Aclass%20Cons%5BT%5D%28val%20head%3A%20T%2C%20val%20tail%3A%20List%5BT%5D%29%20extends%20List%5BT%5D%20%7B%0A%20%20def%20isEmpty%20%3D%20false%0A%20%20//%20head%20%u548C%20tail%20%u5DF2%u7ECF%u5728%u521D%u59CB%u5316%u4E2D%u5B9E%u73B0%0A%7D%0A%0Aclass%20Nil%5BT%5D%20extends%20List%5BT%5D%20%7B%0A%20%20def%20isEmpty%20%3D%20true%0A%20%20def%20head%3A%20Nothing%20%3D%20throw%20new%20NoSuchElementException%28%22Nil.head%22%29%0A%20%20//%20Nothing%20%u662F%u4EFB%u4F55%u7C7B%u578B%u7684%u5B50%u7C7B%uFF0C%u6240%u4EE5%u4E5F%u662F%20T%20%u7684%u5B50%u7C7B%0A%20%20def%20tail%3A%20Nothing%20%3D%20throw%20new%20NoSuchElementException%28%22Nil.tail%22%29%0A%7D%0A%60%60%60%0A%0A%u5728%20week4%20%u4E2D%u65B0%u5EFA%u4E00%u4E2A%20scala%20worksheet%uFF0C%u6D4B%u8BD5%u4E00%u4E0B%u4E0A%u8FF0%u4EE3%u7801%uFF1A%0A%60%60%60scala%0Apackage%20week4%0A%0Aimport%20week4._%0A%0Aobject%20nth%20%7B%0A%20%20//%20%u521B%u5EFA%u4E00%u4E2A%u542B%u6709%u4E00%u4E2A%u5143%u7D20%u7684%20list%0A%20%20def%20singleton%5BT%5D%28elem%3A%20T%29%20%3D%20new%20Cons%28elem%2C%20new%20Nil%29%0A%20%20%20%20%20%20%20%20//%3E%20singleton%3A%20%5BT%5D%28elem%3A%20T%29week4.Cons%5BT%5D%0A%20%20singleton%5BInt%5D%283%29%20%20%20%20%20%20%20%20%20//%3E%20res0%3A%20week4.Cons%5BInt%5D%20%3D%20week4.Cons@71be98f5%0A%20%20singleton%283%29%20//%20%u7F16%u8BD1%u5668%u53EF%u4EE5%u4ECE%203%20%u63A8%u5230%u51FA%20T%20%u662F%20Int%20%0A%20%20%0A%20%20//%20%u5BFB%u627E%20list%20%u4E2D%u7684%u7B2C%20n%20%u4E2A%u5143%u7D20%0A%20%20def%20nth%5BT%5D%28n%3A%20Int%2C%20xs%3A%20List%5BT%5D%29%3A%20T%20%3D%0A%20%20%20%20if%20%28xs.isEmpty%29%20throw%20new%20IndexOutOfBoundsException%0A%20%20%20%20else%20if%20%28n%20%3D%3D%200%29%20xs.head%0A%20%20%20%20else%20nth%28n%20-%201%2C%20xs.tail%29%20%20%20%20%20%20%20%20//%3E%20nth%3A%20%5BT%5D%28n%3A%20Int%2C%20xs%3A%20week4.List%5BT%5D%29T%0A%20%20%20%20%0A%20%20//%20%u521B%u5EFA%u4E00%u4E2A%20list%20%20%3D%20%5B1%2C%202%2C%203%5D%0A%20%20val%20list%20%3D%20new%20Cons%281%2C%20new%20Cons%282%2C%20new%20Cons%283%2C%20new%20Nil%29%29%29%0A%20%20nth%282%2C%20list%29%20%20%20%20%20%20%20%20%20//%3E%20res2%3A%20Int%20%3D%203%0A%7D%0A%60%60%60%0A%0A---%0A%0A%23%23%23%20%u5C0F%u8BB0%0A%3E%20%u8FD9%u91CC%u662F%u8BFE%u7A0B%u524D%u56DB%u6B21%u7684%u5927%u6982%u5185%u5BB9%uFF0C%u56E0%u4E3A%u7B2C%u4E00%u6B21%u8BFE%u662F%u6559%u4F60%u600E%u4E48%u5B89%u88C5%uFF0C%u6240%u4EE5%u5B9E%u9645%u5185%u5BB9%u53EA%u6709%u4E09%u6B21%u8BFE%uFF0C%u540E%u9762%u8FD8%u6709%u4E94%u6B21%u8BFE%u3002%u603B%u4F53%u6765%u8BF4%uFF0C%u51FD%u6570%u5F0F%u7F16%u7A0B%u7ED9%u4EBA%u5F88%u591A%u542F%u53D1%uFF0C%u4F46%u662F%u5982%u679C%u4E0D%u662F%u771F%u6B63%u9700%u8981%u7528%uFF0C%u4E5F%u4E0D%u5B9C%u5360%u7528%u592A%u591A%u65F6%u95F4%u53BB%u5B66%u4E60%u3002%u6691%u5047%u8981%u53BB%u5B9E%u4E60%u4E86%uFF0C%u6CA1%u6709%u65F6%u95F4%u4E0A%u8BFE%uFF0C%u7B49%u4E0B%u5B66%u671F%u518D%u5B66%u5427%u3002%0A%0A