Note that there are some explanatory texts on larger screens.

plurals
  1. POScala for comprehension of sequence inside a Try
    text
    copied!<p>I am writing a Scala program in which there is an operation that creates a sequence. The operation might fail, so I enclose it inside a <code>Try</code>. I want to do sequence creation and enumeration inside a for comprehension, so that a successfully-created sequence yields a sequence of tuples where the first element is the sequence and the second is an element of it.</p> <p>To simplify the problem, make my sequence a <code>Range</code> of integers and define a <code>createRange</code> function that fails if it is asked to create a range of an odd length. Here is a simple for comprehension that does what I want.</p> <pre><code>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 &lt;- createRange(n) x &lt;- r } println(s"$r\t$x") } def main(args: Array[String]) { println("Range length 3") rangeElements(3) println("Range length 4") rangeElements(4) } </code></pre> <p>If you run this it correctly prints.</p> <pre><code>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 </code></pre> <p>Now I would like to rewrite my <code>rangeElements</code> function so that instead of printing as a side-effect it returns a sequence of integers, where the sequence is empty if the range was not created. What I want to write is this.</p> <pre><code>def rangeElements(n: Int):Seq[(Range,Int)] = { for { r &lt;- createRange(n) x &lt;- 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. </code></pre> <p>This gives me two type mismatch compiler errors. The <code>r &lt;- createRange(n)</code> line required <code>Seq[Int]</code> but found <code>scala.util.Try[Nothing]</code>. The <code>x &lt;- r</code> line required <code>scala.util.Try[?]</code> but found <code>scala.collection.immutable.IndexedSeq[Int]</code>.</p> <p>Presumably there is some type erasure with the <code>Try</code> that is messing me up, but I can't figure out what it is. I've tried various <code>toOption</code> and <code>toSeq</code> qualifiers on the lines in the for comprehension to no avail.</p> <p>If I only needed to yield the range elements I could explicitly handle the <code>Success</code> and <code>Failure</code> conditions of <code>createRange</code> myself as suggested by the first two answers below. However, I need access to both the range and its individual elements.</p> <p>I realize this is a strange-sounding example. The real problem I am trying to solve is a complicated recursive search, but I don't want to add in all its details because that would just confuse the issue here.</p> <p>How do I write <code>rangeElements</code> to yield the desired sequences?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload