Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is the preferred way to implement 'yield' in Scala?
    text
    copied!<p>I am doing writing code for PhD research and starting to use Scala. I often have to do text processing. I am used to Python, whose 'yield' statement is extremely useful for implementing complex iterators over large, often irregularly structured text files. Similar constructs exist in other languages (e.g. C#), for good reason.</p> <p>Yes I know there have been previous threads on this. But they look like hacked-up (or at least badly explained) solutions that don't clearly work well and often have unclear limitations. I would like to write code something like this:</p> <pre><code>import generator._ def yield_values(file:String) = { generate { for (x &lt;- Source.fromFile(file).getLines()) { # Scala is already using the 'yield' keyword. give("something") for (field &lt;- ":".r.split(x)) { if (field contains "/") { for (subfield &lt;- "/".r.split(field)) { give(subfield) } } else { // Scala has no 'continue'. IMO that should be considered // a bug in Scala. // Preferred: if (field.startsWith("#")) continue // Actual: Need to indent all following code if (!field.startsWith("#")) { val some_calculation = { ... do some more stuff here ... } if (some_calculation &amp;&amp; field.startsWith("r")) { give("r") give(field.slice(1)) } else { // Typically there will be a good deal more code here to handle different cases give(field) } } } } } } } </code></pre> <p>I'd like to see the code that implements generate() and give(). BTW give() should be named yield() but Scala has taken that keyword already.</p> <p>I gather that, for reasons I don't understand, Scala continuations may not work inside a for statement. If so, generate() should supply an equivalent function that works as close as possible to a for statement, because iterator code with yield almost inevitably sits inside a for loop.</p> <p>Please, I would prefer not to get any of the following answers:</p> <ol> <li>'yield' sucks, continuations are better. (Yes, in general you can do more with continuations. But they are hella hard to understand, and 99% of the time an iterator is all you want or need. If Scala provides lots of powerful tools but they're too hard to use in practice, the language won't succeed.)</li> <li>This is a duplicate. (Please see my comments above.)</li> <li>You should rewrite your code using streams, continuations, recursion, etc. etc. (Please see #1. I will also add, technically you don't need for loops either. For that matter, technically you can do absolutely everything you ever need using <a href="http://en.wikipedia.org/wiki/SKI_combinator_calculus" rel="nofollow noreferrer">SKI combinators</a>.)</li> <li>Your function is too long. Break it up into smaller pieces and you won't need 'yield'. You'd have to do this in production code, anyway. (First, "you won't need 'yield'" is doubtful in any case. Second, this isn't production code. Third, for text processing like this, very often, breaking the function into smaller pieces -- especially when the language <strong>forces</strong> you to do this because it lacks the useful constructs -- only makes the code <em>harder</em> to understand.)</li> <li>Rewrite your code with a function passed in. (Technically, yes you can do this. But the result is no longer an iterator, and chaining iterators is much nicer than chaining functions. In general, a language should not force me to write in an unnatural style -- certainly, the Scala creators believe this in general, since they provide shitloads of syntactic sugar.)</li> <li>Rewrite your code in this, that, or the other way, or some other cool, awesome way I just thought of.</li> </ol>
 

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