我已经编码了两年了。我无法说我是专家。
我参加过函数式编程课程,其中我们使用了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中是否有一种方法可以定义一个列表,但是不必包含与元素相同类型的列表?
答案 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 - 你正在与之抗争。只要您认为自己需要Any
或List[Any]
,就会有更好,更惯用,更像Scala的解决方案。
在Scala代码中使用asInstanceOf
或isInstanceOf
也是不正常的。它们故意隐藏着长篇名称 - 除非在极少数情况下,否则不打算使用它们。
相反,使用模式匹配。它对您来说相当于isInstanceOf
和asInstanceOf
,但更简洁,更不容易出错。同样,任何介绍性Scala文本都应该很好地覆盖模式匹配以及如何使用它(例如chapter 15 again)。