0

シーケンスを作成する操作がある Scala プログラムを書いています。操作が失敗する可能性があるため、 で囲みTryます。for 内包内でシーケンスの作成と列挙を行いたいので、正常に作成されたシーケンスは、最初の要素がシーケンスであり、2 番目の要素がその要素であるタプルのシーケンスを生成します。

問題を単純化するために、Range整数のシーケンスcreateRangeを作成し、奇数の長さの範囲を作成するように求められた場合に失敗する関数を定義します。これは、私が望むことを理解するための簡単なものです。

import scala.util.Try

def createRange(n: Int): Try[Range] = {
  Try {
    if (n % 2 == 1) throw new Exception
    else Range(0, n)
  }
}

def rangeElements(n: Int) {
  for {
    r <- createRange(n)
    x <- r
  } println(s"$r\t$x")
}

def main(args: Array[String]) {
  println("Range length 3")
  rangeElements(3)

  println("Range length 4")
  rangeElements(4)
}

これを実行すると、正しく印刷されます。

Range length 3
Range length 4
Range(0, 1, 2, 3)   0
Range(0, 1, 2, 3)   1
Range(0, 1, 2, 3)   2
Range(0, 1, 2, 3)   3

ここで、関数を書き直してrangeElements、副作用として出力するのではなく、整数のシーケンスを返すようにします。範囲が作成されていない場合、シーケンスは空です。書きたいのはこれです。

def rangeElements(n: Int):Seq[(Range,Int)] = {
  for {
    r <- createRange(n)
    x <- r
  } yield (r, x)
}
// rangeElements(3) returns an empty sequence
// rangeElements(4) returns the sequence (Range(0,1,2,3), 0), (Range(0,1,2,3), 1) etc.

これにより、2 つの型の不一致コンパイラ エラーが発生します。r <- createRange(n)行が必要ですSeq[Int]が見つかりましたscala.util.Try[Nothing]x <- r行が必要ですscala.util.Try[?]が見つかりましたscala.collection.immutable.IndexedSeq[Int]

おそらく、Try私を台無しにしているタイプの消去がありますが、それが何であるかわかりません。私は理解のために、行でさまざまな修飾子を試しましtoOptiontoSeqが、役に立ちませんでした。

範囲要素のみを生成する必要がある場合は、以下の最初の 2 つの回答で示唆されているように、自分自身のSuccessandFailure条件を明示的に処理できます。createRangeただし、範囲とその個々の要素の両方にアクセスする必要があります。

これは奇妙に聞こえる例だと思います。私が解決しようとしている本当の問題は複雑な再帰検索ですが、ここで問題を混乱させるだけなので、その詳細をすべて追加したくありません。

rangeElements目的のシーケンスを生成するにはどうすればよいですか?

4

2 に答える 2

3

for 内包表記を map/flatMap 実装に変換すると、問題が明確になります ( Scala Language Spec 6.19で説明されています)。flatMap には結果の型Try[U]がありますが、関数はSeq[Int].

for {
  r <- createRange(n)
  x <- r
} yield x

createRange(n).flatMap {
  case r => r.map {
    case x => x
  }
}

メソッドを使用しない理由はありますgetOrElseか?

def rangeElements(n: Int):Seq[Int] =
  createRange(n) getOrElse Seq.empty
于 2013-07-24T22:24:11.463 に答える
1

Tryは偶数の場合または奇数のSuccess場合になります。一致してそれらの値を抽出します。有効な が含まれ、が含まれます。return を返す代わりに、空の.RangenFailureExceptionnrangeElementsSuccessRangeFailureExceptionExceptionSeq

import scala.util.{Try, Success, Failure}

def createRange(n: Int): Try[Range] = {
  Try {
    if (n % 2 == 1) throw new Exception
    else Range(0, n)
  }
}

def rangeElements(n: Int):Seq[Tuple2[Range, Int]] = createRange(n) match {
  case Success(s) => s.map(xs => (s, xs))
  case Failure(f) => Seq()
}    

scala> rangeElements(3)
res35: Seq[(Range, Int)] = List()

scala> rangeElements(4)
res36: Seq[(Range, Int)] = Vector((Range(0, 1, 2, 3),0), (Range(0, 1, 2, 3),1), (Range(0, 1, 2, 3),2), (Range(0, 1, 2,3),3))
于 2013-07-24T22:18:11.327 に答える