1

少し 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 で Java メソッド X を記述する最良の方法は何ですか?」と尋ねる適切な Scala ワールドのフォーラムはどこですか。私は自分自身がこの質問をよくしていることに気づきます。

4

3 に答える 3

5
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)
}

(または類似)

于 2013-06-25T15:13:40.230 に答える
1

これは、この問題に対する別の見方です。おそらく、この特定のケースで使用するものではありませんが、知っておく価値があります。

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 の場合に終了する要素の親のストリームを定義することから始めます。strict フラグが true の場合は、最初のものを削除します。stopAtまたは で何かをヒットした場合も、検索を停止しますPsiFile。これらの制約内で、一致する最初のものを取得 (およびキャスト) し、何も取得しなかった場合はそれを返すか、null を返します。

少し練習すれば、ループよりもこの種のロジックに従う方が実際には簡単です。これは、終了条件がここよりもループ内でより暗黙的であるためです。ここでは、検索をやめたとき ( takeWhile) と目的 ( ) をはっきりと述べているだけですcollectFirst

注:次のようにinstanceOf定義されていると仮定しています

def instanceOf(a: AnyRef, cs: Seq[Class[_]]) = cs.exists(_ isInstance a)
于 2013-06-25T16:10:53.150 に答える
1

でscalaを使うのは難しいnullです。そして、慣用的な scala コードを で取得することはできませんwhile

あなたは@Nullableand を持っています@NotNull- scala ではOption[T]andTです。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]}
}
于 2013-06-25T15:12:50.330 に答える