(Scala)列表可以包含列表作为元素

时间:2015-12-28 02:18:26

标签: list scala functional-programming nested-lists

我已经编码了两年了。我无法说我是专家。

我参加过函数式编程课程,其中我们使用了Common Lisp。我听到很多关于Scala的好东西,作为" new "语言,想学习它。我读了一本关于基础知识的书,并希望将我们在Lisp中完成的所有代码重写为Scala。几乎所有代码都通过列表,这是我发现问题的地方。我可以通过递归遍历我将其设置为List[Any]的列表来解决大多数问题 - 例如:

def reverse(thelist: List[Any]):List[Any].....

但是我发现除了.isInstanceOf[List[Any]]

之外,没有一种特定的方法来检查列表的头部是否是列表本身

一开始就没问题,但现在我遇到了问题。 Any并不具体,特别是对于比较元素。如果我想要一个等效的列表,让我们说只有Int,我可以创建一个List[Int],它只能将Int值作为元素,没有可以是List [Int]本身。另一方面,编写List[List[Int]]具有相同的问题,但相反,因为每个元素都必须是List

作为一种解决方案,我尝试将原始列表设置为List[Either[Int,List[Int]]],但这只会产生更多问题,因为现在我必须不断编写.isInstanceOf.asInstanceOf我的ifs和递归调用,这是耗时的,并使代码更难理解。但即使List[Either[Int,List[Int]]]也是一个临时解决方案,因为它只有一个层次。列表可以包含可以包含列表的列表......等等。

Scala是否提供了一个我还不知道的更优雅的解决方案,例如以某种方式使用类或对象,或者简单优雅的解决方案,还是我坚持编写这种代码?为了使我的问题更具体,Scala中是否有一种方法可以定义一个列表,但是不必包含与元素相同类型的列表?

1 个答案:

答案 0 :(得分:11)

Scala不仅仅是具有不同语法的Common Lisp。对所有内容使用列表是Lisp特有的,而不是你用其他语言做的事情。

在Scala中,使用异构列表 - List[Any] - 对于任何事情都是不正常的。如果你愿意,你当然可以,但这不是通常编写Scala代码的方式。当你刚刚开始学习这门语言时,肯定不是你应该写的那种代码。

包含数字和列表混合的列表实际上不是列表 - 它是一棵树。在Scala中,我们根本不使用List来表示树 - 我们定义了一个正确的树数据类型。任何介绍性Scala文本都包含此示例。 (例如,参见chapter 15 of Programming in Scala中的表达式树。)

至于你的reverse示例,在Scala中我们通常不会写:

def reverse(thelist: List[Any]): List[Any]

相反,我们写道:

def reverse[T](theList: List[T]): List[T]

适用于List[Any],但也可用于更具体的类型,例如List[Int]

如果你坚持用另一种方式做,那你就不是在学习Scala - 你正在与之抗争。只要您认为自己需要AnyList[Any],就会有更好,更惯用,更像Scala的解决方案。

在Scala代码中使用asInstanceOfisInstanceOf也是不正常的。它们故意隐藏着长篇名称 - 除非在极少数情况下,否则不打算使用它们。

相反,使用模式匹配。它对您来说相当于isInstanceOfasInstanceOf,但更简洁,更不容易出错。同样,任何介绍性Scala文本都应该很好地覆盖模式匹配以及如何使用它(例如chapter 15 again)。