我最近开始阅读Paul Chiusano和RúnarBjarnason撰写的“ Scala中的函数编程”一书,作为学习FP的一种方法。我想学习它,因为它会打开我的脑袋,扭曲我的思维方式,也希望能让我成为一个更好的程序员,或者我希望。
在他们的书中,Chp。 3,他们定义了一个基本的单链表类型如下:
package fpinscala.datastructures
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x,xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1.0
case Cons(0.0, _) => 0.0
case Cons(x,xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
我现在正在实现tail方法,它应该类似于Scala库中定义的tail方法。我想这里的想法是在List对象中定义一个tail方法,他们称之为伴侣方法,然后在另一个文件(如主文件)中正常调用它。
到目前为止,我有这个:
def tail[A](ls: List[A]): List[A] = ls match {
case Nil => Nil
case Cons(x,xs) => xs
}
然后我在另一个文件夹中创建了一个Main文件:
package fpinscala.datastructures
object Main {
def main(args:Array[String]):Unit = {
println("Hello, Scala !! ")
val example = Cons(1, Cons(2, Cons(3, Nil)))
val example2 = List(1,2,3)
val example3 = Nil
val total = List.tail(example)
val total2 = List.tail(example3)
println(total2)
}
}
这有效并且给了我:
Hello, Scala !!
Cons(2,Cons(3,Nil))
我的问题是:
这可能是编写尾部方法的正确方法,正如作者所预期的那样吗?这个包装结构是否正确?因为我感觉非常不对,虽然我只是跟着作者的包裹。
我也不知道我是否应该使用特定类型而不是编写多态方法(这是名字吗?)...
请耐心等待我,因为我是FP的新手。
答案 0 :(得分:2)
在默认的Scala列表实现中,尝试获取空列表的尾部会抛出UnsupportedOperationException。所以你可能想要更像
的东西def tail[A](ls: List[A]): List[A] = ls match {
case Nil => throw new UnsupportedOperationException()
case Cons(x,xs) => xs
}
另外,qantik的回答他建议使用::运算符可以使用Scala的默认列表实现,但由于没有在此自定义列表实现上定义的::方法,因此它不起作用。
最后,您可能需要考虑定义尾部,而不是执行
val list = List(1, 2, 3)
val restOfList = tail(list).
你可以改为
val list = List(1, 2, 3)
val restOfList = list.tail
这将需要在List trait上定义方法,而不是在List对象中。
答案 1 :(得分:-1)
看起来没问题。怎么样?
<uses-sdk tools:overrideLibrary="the library package name" />
<uses-sdk tools:node="replace" />