【问题标题】:(Scala) Lists that can contain lists as elements(Scala) 可以包含列表作为元素的列表
【发布时间】:2015-12-28 02:18:26
【问题描述】:

我已经编码两年了。我不能说我是专家。

我参加了一门函数式编程课程,其中我们使用了 Common Lisp。我听说了很多关于 Scala 的好消息,作为一种“”语言并想学习它。我读了一本关于基础知识的书,想将我们在 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]]],但这只会产生更多问题,因为现在我必须在所有 if 和递归调用中不断编写 .isInstanceOf.asInstanceOf,这非常耗时,并且使代码更难理解。但即使List[Either[Int,List[Int]]] 也是一个临时解决方案,因为它只深入一层。一个列表可以包含一个可以包含一个列表的列表......等等。

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

【问题讨论】:

  • 请清理您的格式。缺乏可读性。
  • 重新格式化。希望对您有所帮助。

标签: list scala functional-programming nested-lists


【解决方案1】:

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)。

【讨论】:

  • 感谢您的回复,把事情搞清楚了。作为后续我不得不问的问题,这是否意味着与 Lisp 在 Scala 中的列表等效的是树?
  • @Nik.S.不完全的。 Lips 对所有内容都使用列表,有时它很好,有时它不是。 Scala(和许多其他语言)为特定问题选择特定的数据结构。
  • 我添加了 Scala 编程 第 15 章的链接,其中展示了如何使用一组相关的案例类来表示(作为特定类型的示例树)表达式树。在 Lisp 中,您将为此使用列表;在 Scala 中,您采用完全不同的方法,根本不涉及 Lisp 的“等价物”。如果您停止从等价的角度思考并按其条款接近 Scala,那会更好。将所有内容都翻译成语言 A 并不是学习语言 B 的好方法,无论 A 和 B 是什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 2020-01-10
  • 1970-01-01
  • 2015-04-09
  • 2018-02-11
相关资源
最近更新 更多