2016-08-21 170 views
3

我最近开始阅读Paul Chiusano和RúnarBjarnason编写的Scala中的函数式编程,作为学习FP的一种手段。我想学习它,因为它会打开我的头,扭曲我的思维方式,并希望使我成为一个更好的程序员整体,或所以我希望。Scala的函数式编程练习

在他们的书中, 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: _*)) 
} 

我现在正在实施的尾法,这应同样工作在斯卡拉库中定义的尾巴方法。我想这里的想法是在List对象中定义一个尾部方法,他们称之为伴随方法,然后在另一个文件(如Main文件)中正常调用它。

到目前为止,我有这样的:

def tail[A](ls: List[A]): List[A] = ls match { 
    case Nil => Nil 
    case Cons(x,xs) => xs 
    } 

然后我创建了另一个文件夹中的主文件:

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

对我来说这似乎很完美。 虽然: 1.你不想在密封的特质之外显示出缺点,所以最好把它变成私人的 2.你为什么在你的主要功能中需要示例和总变量? – mavarazy

+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对象中。

-1

看起来没问题。关于什么?

def tail[A](xs: List[A]): List[A] = xs match { 
    case Nil => Nil 
    case head :: xxs => xxs 
}