[英]How do I write this method in Scala, or what is the best way to deal with early returns
玩弄一点Scala,似乎您无法从函数中早返回。
我发现简单的无缩进代码很容易遵循。 我最初的尝试创建了一个大的嵌套结构。 打电话给我挑剔,但我不喜欢看到以下内容:
}
}
}
在Scala中编写以下方法的最佳方法是什么?
是否有可能以减少嵌套的方式进行编程,还是我会在整个过程中与Scala的功能设计理念进行斗争?
@Nullable
public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element,
@NotNull Class<T> aClass,
boolean strict,
@NotNull Class<? extends PsiElement>... stopAt) {
if (element == null) return null;
if (strict) {
element = element.getParent();
}
while (element != null && !aClass.isInstance(element)) {
if (instanceOf(element, stopAt)) return null;
if (element instanceof PsiFile) return null;
element = element.getParent();
}
//noinspection unchecked
return (T)element;
}
我的尝试:
def getParentOfType[T](element: PsiElement, aClass: Class, strict: Boolean): T[_ <: PsiElement] = {
element match {
case null => null
case _ => {
var el = if (strict) {
element.getParent
} else element
while(el != null) {
if (aClass isInstance el) {
return el
}
if (el.isInstanceOf[PsiFile]) return null;
el = el.getParent()
}
}
}
}
另外,在Scala世界中哪个合适的论坛问“在Scala中编写Java方法X的最佳方法是什么?”。 我发现自己经常问这个问题。
def getParentOfType[T](element: PsiElement, aClass: Class, strict: Boolean):
T[_ <: PsiElement] = element match {
case null => null
case el if strict => getParentOfType(el.getParent, aClass, false)
case el if aClass isInstance el => el
case el if el.isInstanceOf[PsiFile] => null
case el => getParentOfType(el.getParent, aClass, false)
}
(或类似)
使用带有null
scala很难。 而且,使用while
无法获得惯用的Scala代码。
你有@Nullable
和@NotNull
-在Scala中是Option[T]
和T
。 您可以用递归方法替换while
。
例如,这是我尝试将您的方法转换为scala(未经测试):
getParentOfType[T <: PsiElement](element: Option[PsiElement],
aClass: Class[T],
strict: Boolean,
stopAt: Class[_ <: PsiElement]*): Option[T] = element flatMap { el =>
@tailrec def loop(element: PsiElement): Option[PsiElement] {
if (element == null || aClass.isInstance(element))
Option(element)
else if (instanceOf(element, stopAt) || element.isInstanceOf[PsiFile])
None
else
loop(element.getParent())
}
loop(if (strict) el.getParent() else el).map{_.asInstanceOf[T]}
}
这是一个不同的看法。 可能不是我在这种特殊情况下使用的,但值得了解。
def getParentOfType[A >: Null <: PsiElement](
element: PsiElement, aClass: Class[A],
strict: Boolean, stopAt: Class[_ <: PsiElement]*
): A =
Iterator.iterate(element)(_.getParent).
takeWhile(_ != null).
drop(if (strict) 1 else 0).
takeWhile(e => !instanceOf(e, stopAt) && !e.isInstanceOf[PsiFile]).
collectFirst{ case x if aClass isInstance x => x.asInstanceOf[A] }.
orNull
在这里,您首先定义元素的父级流,如果它为null,则终止。 如果您的严格标志为true,则删除第一个; 如果您在stopAt
或PsiFile
命中了某些内容,也将停止搜索。 在这些约束条件下,您获得(并强制转换)匹配的第一项内容,然后返回该内容或返回null(如果未获得任何内容)。
通过一点实践,遵循这种逻辑实际上比循环更容易 ,因为终止条件比此处更隐含。 在这里,您只需要声明停止搜索( takeWhile
)及其后的内容( collectFirst
)即可。
注意:我假设instanceOf
定义为
def instanceOf(a: AnyRef, cs: Seq[Class[_]]) = cs.exists(_ isInstance a)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.