当匹配的模式为Nil并且我们要返回Nil时,什么是适当的返回值?
我是Scala和函数式编程的新手。所以这是我的疑问。我们应该返回Nil
还是数据类型本身呢?例如,当匹配的模式为Nil并且我们要返回Nil时,什么是适当的返回值?
def drop[A](l: List[A], n: Int): List[A] = {
if (n <= 0) l
else l match {
case Nil => Nil
case Cons(_, t) => drop(t, n - 1)
}
}
这是丢弃来自单链表第一n
头元件的功能。在这里,对于第一种情况,我应该返回Nil
(也许是一种好的做法),或者我应该返回l
(因为那么我们不需要构造Nil
对象)?
Nil
对象只有一个单例实例。当你写Nil
你不会每次创建一个新的,你只使用唯一存在的。
通常最好写Nil
,因为它更具可读性。至少这是我一直在阅读和写作的内容。
由于只有一个NIL实例,所以它并不重要,因为它是实际相同的对象。
现在真正的问题是:什么更可读?
- 如果你想清楚,当你
Nil
,则返回Nil
,然后写Nil => Nil
- 如果它似乎更符合逻辑返回
l
,即使它实际上是Nil
,然后写Nil => l
恕我直言,你的情况,Nil => Nil
对我来说比较清楚。
你可以举个例子来说明返回值是否为'Nil'但写入'l'使得代码更具可读性吗?我已经看到了我有一个累加器初始化为'Nil'的实例,它被返回是因为它可能会或可能不会累积更多的值。但我还没有看到你提到的情况。 – aa8y 2015-02-24 21:00:28
如果Nil => Nil
真的是你的主要逻辑流程中得罪了你的感情,你可能会考虑充实,我的图书馆式的隐含类的新方法中隐藏:
implicit class ListWithIfNonEmpty[A](list: List[A]) {
/**
* Replaces a list with a new one in the case that it is
* not empty. newList is probably a conversion of the original
* list, but the original list is available in the caller's
* scope, so no need to pass it as a parameter.
*/
def ifNonEmpty[B](newList: => List[B]): List[B] = list match {
case Nil => Nil
case _ => newList
}
}
然后你drop
方法变得稍微更清洁:
def drop[A](l: List[A], n: Int): List[A] = l.ifNonEmpty {
if (n <= 0) l else drop(l.tail, n - 1)
}
也许这个新方法的名字不那么尴尬。在这种情况下,这种事情对于您的主逻辑流程来说只是一个巨大的胜利,在这种情况下,方法名称使得您要实现的语义非常明显。但你得到了漂移。
谢谢!这就说得通了。 – aa8y 2015-02-24 20:50:10