Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>In addition to Daniel's answer, keep in mind that <code>Stream</code> is useful for short-circuiting evaluations. For example, suppose I have a huge set of functions that take <code>String</code> and return <code>Option[String]</code>, and I want to keep executing them until one of them works:</p> <pre><code>val stringOps = List( (s:String) =&gt; if (s.length&gt;10) Some(s.length.toString) else None , (s:String) =&gt; if (s.length==0) Some("empty") else None , (s:String) =&gt; if (s.indexOf(" ")&gt;=0) Some(s.trim) else None ); </code></pre> <p>Well, I certainly don't want to execute the <em>entire</em> list, and there isn't any handy method on <code>List</code> that says, "treat these as functions and execute them until one of them returns something other than <code>None</code>". What to do? Perhaps this:</p> <pre><code>def transform(input: String, ops: List[String=&gt;Option[String]]) = { ops.toStream.map( _(input) ).find(_ isDefined).getOrElse(None) } </code></pre> <p>This takes a list and treats it as a <code>Stream</code> (which doesn't actually evaluate anything), then defines a new <code>Stream</code> that is a result of applying the functions (but that doesn't evaluate anything either yet), then searches for the first one which is defined--and here, magically, it looks back and realizes it has to apply the map, and get the right data from the original list--and then unwraps it from <code>Option[Option[String]]</code> to <code>Option[String]</code> using <code>getOrElse</code>.</p> <p>Here's an example:</p> <pre><code>scala&gt; transform("This is a really long string",stringOps) res0: Option[String] = Some(28) scala&gt; transform("",stringOps) res1: Option[String] = Some(empty) scala&gt; transform(" hi ",stringOps) res2: Option[String] = Some(hi) scala&gt; transform("no-match",stringOps) res3: Option[String] = None </code></pre> <p>But does it work? If we put a <code>println</code> into our functions so we can tell if they're called, we get</p> <pre><code>val stringOps = List( (s:String) =&gt; {println("1"); if (s.length&gt;10) Some(s.length.toString) else None }, (s:String) =&gt; {println("2"); if (s.length==0) Some("empty") else None }, (s:String) =&gt; {println("3"); if (s.indexOf(" ")&gt;=0) Some(s.trim) else None } ); // (transform is the same) scala&gt; transform("This is a really long string",stringOps) 1 res0: Option[String] = Some(28) scala&gt; transform("no-match",stringOps) 1 2 3 res1: Option[String] = None </code></pre> <p>(This is with Scala 2.8; 2.7's implementation will sometimes overshoot by one, unfortunately. And note that you <em>do</em> accumulate a long list of <code>None</code> as your failures accrue, but presumably this is inexpensive compared to your true computation here.)</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