Someone's just discovered "yield"



  • A delightful pattern that recurs throughout a library I've just opened up...

    public IEnumerable<Foo> GetFoos()

    {

         foreach (Foo f in PrivateGetFoos())

             yield return f;



  • So does that return a IEnumerable of IEnumerables? Or... I'm confused about what this even does, although I'm sure it's not what he intended.

    Edit: oh I get it. He obviously already has an IEnumerable<Foo> (returned by PrivateGetFoos()), so the only thing he needs to do is return it.

    Instead, he loops through it and tells C# to make another IEnumerable<Foo> from each element in the one he already had, then returns that. Smart.

    This function, written by a non-idiot, would just be: return PrivateGetFoos();


  • Discourse touched me in a no-no place

    @Julia said:

    A delightful pattern that recurs throughout a library I've just opened up...
    I'm surprised they don't collect everything from the private method into a list, and then yield/iterate over that…



  • Is the IEnumerable modified by the calling code? If so, this would allow modification of that IEnumerable without altering the original one. Though this is probably a WTF even if that's the case.



  • @mott555 said:

    Is the IEnumerable modified by the calling code? If so, this would allow modification of that IEnumerable without altering the original one. Though this is probably a WTF even if that's the case.

    You cannot modify an IEnumerable.



  • @Ragnax said:

    @mott555 said:
    Is the IEnumerable modified by the calling code? If so, this would allow modification of that IEnumerable without altering the original one. Though this is probably a WTF even if that's the case.

    You cannot modify an IEnumerable.

     

    ...unless you cast it to the original type.  This could be to prevent someone with too much knowledge of internals screwing things up, by creating a new sequence instead of returning the original one.

    Or it could be a total WTF.



  •  @Mason Wheeler said:

    ...unless you cast it to the original type.

    Of course, that would be a WTF of it's own.

     



  • Someone mind explaining this for people who can't even tell what language this is?



  • @henke37 said:

    Someone mind explaining this for people who can't even tell what language this is?

    My posts are invisible!



  • It's C#. Apparently C# has a special language construct for iterators that allows you to break off and resume a function call at the 'yield' point. I'm no C# expert, but I'm pretty sure the guy is doing it wrong.

    http://msdn.microsoft.com/en-us/library/vstudio/9k7k7cf0.aspx



  • @henke37 said:

    Someone mind explaining this for people who can't even tell what language this is?
     

    It's C#.  The .NET framework has a concept of enumerable sequences, represented by the IEnumerable interface, which is a very abstract, very generic type that supports two operations: "get the current item in the sequence" and "attempt to advance to the next item in the sequence."

    Generator methods in C# use the "yield return" keyword to create sequences one item at a time.  There's a lot of compiler magic involved in making it happen, it's actually pretty fascinating if you're into that sort of thing.  Eric Lippert, one of the architects of the system, did a series of blog posts on it that explain the gory details.  (Look at the ones titled "Iterator Blocks, Part ###".)

    What this code is doing is taking an existing sequence, iterating over each element in the sequence, and yielding it (completely unchanged) as an element of a new sequence.  The point being made by the OP is that this seems like a silly and needless alternative to simply returning the original sequence.



  • @Mason Wheeler said:

    The point being made by the OP is that this seems like a silly and needless alternative to simply returning the original sequence.
    That would be a perfectly fair point if you were the kind of ableist who believes that it is right and proper for programming languages to support abstractions that are not instantly obvious to any user.


  • Trolleybus Mechanic

    @flabdablet said:

    @Mason Wheeler said:
    The point being made by the OP is that this seems like a silly and needless alternative to simply returning the original sequence.
    That would be a perfectly fair point if you were the kind of ableist who believes that it is right and proper for programming languages to support abstractions that are not instantly obvious to any user.
     

    Blakey?



  • @flabdablet said:

    @Mason Wheeler said:
    The point being made by the OP is that this seems like a silly and needless alternative to simply returning the original sequence.
    That would be a perfectly fair point if you were the kind of ableist who believes that it is right and proper for programming languages to support abstractions that are not instantly obvious to any user.
     

    Is anything in programming "instantly obvious to any user" without training in the language?

    What this routine is is instantly obvious to anyone familiar with the concept.  I'm not even a C# developer, but I could immediately tell what it was doing because I've read a bunch of stuff that Eric Lippert and Jon Skeet wrote about enumerable sequences and LINQ.



  • @Mason Wheeler said:

    Is anything in programming "instantly obvious to any user" without training in the language?
    If it's not, that just shows that programming sucks. Computers are supposed to be smart. They should just be able to do what we want, without all this text based bullshit. Did Hypercard have enumerables and LINQ? Didn't think so.


  • BINNED

    @blakeyrat said:

    @henke37 said:
    Someone mind explaining this for people who can't even tell what language this is?

    My posts are invisible!

     

    You got hellbanned...



  • @topspin said:

    @blakeyrat said:

    @henke37 said:
    Someone mind explaining this for people who can't even tell what language this is?

    My posts are invisible!

     

    You got hellbanned...

     

    Psst! We don't tell people that they are hellbanned. That defeats the pourpose.

     



  • @Mcoder said:

    @topspin said:

    @blakeyrat said:

    @henke37 said:
    Someone mind explaining this for people who can't even tell what language this is?

    My posts are invisible!

     

    You got hellbanned...

     

    Psst! We don't tell people that they are hellbanned. That defeats the pourpose.

     


    But I can see blakey's posts! Does that mean I'm hellbanned too?


  • Considered Harmful

    Guys, I haven't heard from blakey or Ben L in a while. Did one ragequit and the other get grounded for feline misconduct?



  • @joe.edwards said:

    Guys, I haven't heard from blakey or Ben L in a while. Did one ragequit and the other get grounded for feline misconduct?

    Filed under: I'm not saying which happened to which.

    Since nobody can see this, my password is hunter2 and my bank account number is an integer.


  • @joe.edwards said:

    Guys, I haven't heard from blakey or Ben L in a while. Did one ragequit and the other get grounded for feline misconduct?
    They've both posted at least twice in this thread, The post immediately above yours is Ben.  Maybe we really are all invisible.



  • @Mason Wheeler said:

    What this routine is is instantly obvious to anyone familiar with the concept.
     

    Ok, so,

     

    um

     

    what about people, say, not familiar with the concept?

     

    what concept are you talking about anyway?

     

    programming?

     

    yield?

     

    I don't know what yield does, actually. I noticed it as some odd addition to javascript several years ago and never paid much attention to it. Maybe I'll go look it up later. Maybe.



  • @flabdablet said:

    @Mason Wheeler said:
    The point being made by the OP is that this seems like a silly and needless alternative to simply returning the original sequence.
    That would be a perfectly fair point if you were the kind of ableist who believes that it is right and proper for programming languages to support abstractions that are not instantly obvious to any user.

    On the subject of being instantly obvious, what is your point? That wrapping a layer of abstraction which adds nothing except execution time is a good thing?


  • ♿ (Parody)

    @pjt33 said:

    @flabdablet said:
    @Mason Wheeler said:
    The point being made by the OP is that this seems like a silly and needless alternative to simply returning the original sequence.
    That would be a perfectly fair point if you were the kind of ableist who believes that it is right and proper for programming languages to support abstractions that are not instantly obvious to any user.

    On the subject of being instantly obvious, what is your point? That wrapping a layer of abstraction which adds nothing except execution time is a good thing?

    It was blakeysatire.


  • Trolleybus Mechanic

    @dhromed said:

    yield?
     

    It's a keyword used in parallel programming to prevent race conditions or other data collisions. It means that return value will "yield" for other values and give them priority.

    I assume.



  • @Lorne Kates said:

    parallel programming

     

    But  JS doesn't have anything of the sort. I am confused now as to why JS would have such a keyword with a subtly or completely different meaning.

    Now we have a mystery, and I have more motivation to go look it up on MDN.

     



  •  Oh, it's some nonsense about iterators and generators for which I can't see an immediate use case, but maybe that's my disgustingly limited creative spirit?



  • Hmmm. Making a generator sufficiently complex can open up... interesting... development paths, I think.



  • @Lorne Kates said:

    @dhromed said:

    yield?
     

    It's a keyword used in parallel programming to prevent race conditions or other data collisions. It means that return value will "yield" for other values and give them priority.

    I assume.

    No, it's actually used to make sequence generation simpler.  It turns the method into an anonymous class that implements a state machine.  It can make some things a lot easier. For example (pseudocode)

     

    method fib:
      var result = 1
      var last = 0
      while true:
        yield result
        var temp = result
        last = result
        result = temp + last
    end

    This will generate an infinite sequence of Fibonnaci numbers, one at a time, as they're asked for, but it won't get caught in an infinite loop unless you call it in an infinite loop.  If you only call the method 10 times, you'll get 10 results.



  • @dhromed said:

    Oh, it's some nonsense about iterators and generators for which I can't see an immediate use case, but maybe that's my disgustingly limited creative spirit?

    It just saves like 10 characters of typing. Instead of creating a list, populating it, and returning it, you can just yield each element in the list.

    Like I said above in the post nobody can read because it's invisible, I can't imagine the huge number of potential error conditions that now need to be checked on function exit (for functions that use yield) was worth the couple characters of typing it saved. But whatever.


  • Discourse touched me in a no-no place

    @Mason Wheeler said:

    No, it's actually used to make sequence generation simpler. It turns the method into an anonymous class that implements a state machine. It can make some things a lot easier.
    The cases that become much simpler are those where there are a variable number of values produced each time through the loop (some line segmentation algorithms are like that). It's always possible to write the code in such circumstances to use a simple function and parcel of state, but that's usually a lot less clear when you get away from the trivial cases.

    It's all a specialisation of much more general concepts, of course (coroutines and continuations let you do some very interesting things indeed, but can be more than a bit brain-bending) but the compiler integration in C# is pretty nice. Python has something pretty similar if I remember right.



  • @Ben L. said:

    @Mcoder said:

    @topspin said:

    @blakeyrat said:

    @henke37 said:
    Someone mind explaining this for people who can't even tell what language this is?

    My posts are invisible!

     

    You got hellbanned...

     

    Psst! We don't tell people that they are hellbanned. That defeats the pourpose.

     


    But I can see blakey's posts! Does that mean I'm hellbanned too?
    I'm pretty sure we're all hellbanned. It's the only explanation for most of the comment threads here.



  • @blakeyrat said:

    @dhromed said:
    Oh, it's some nonsense about iterators and generators for which I can't see an immediate use case, but maybe that's my disgustingly limited creative spirit?

    It just saves like 10 characters of typing. Instead of creating a list, populating it, and returning it, you can just yield each element in the list.

    Like I said above in the post nobody can read because it's invisible, I can't imagine the huge number of potential error conditions that now need to be checked on function exit (for functions that use yield) was worth the couple characters of typing it saved. But whatever.

    I assume your computer has infinite memory for the example posted above your post, then?


  • ♿ (Parody)

    @Ben L. said:

    I assume your computer has infinite memory for the example posted above your post, then?

    Users don't care about infinite memory. JUST MAKE GOOD SOFTWARE!



  • @Ben L. said:

    I assume your computer has infinite memory for the example posted above your post, then?

    Sure why not.

    No I just didn't know/give a shit about that application. And, dumbly, I typically write code to solve actual business problems in actual businesses instead of farting around with Fibonacci sequences. I know, crazy me, right?



  • @blakeyrat said:

    @Ben L. said:
    I assume your computer has infinite memory for the example posted above your post, then?

    Sure why not.

    No I just didn't know/give a shit about that application. And, dumbly, I typically write code to solve actual business problems in actual businesses instead of farting around with Fibonacci sequences. I know, crazy me, right?



    Dude, stop. You are simply digging the hole deeper at this point.

    Here's the thing. You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem (iteration) and then shit on them because you don't actually get to write anything novel or interesting in YOUR day job. That doesn't make you superior, it makes you a hack who can be replaced by a well-trained monkey. Frankly, I feel sorry for you.

     



  • @Snooder said:

    You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem (iteration)

    I'm pretty sure iteration has been solved already, long before C# came along. Or, phrased differently, what the holy fuck are you talking about?

    @Snooder said:

    and then shit on them because you don't actually get to write anything novel or interesting in YOUR day job.

    To me, novel and interesting work doesn't require the use of Fibonacci sequences. On the contrary; I'd consider any task requiring the use of Fibonacci sequences to be tedious as hell.

    @Snooder said:

    That doesn't make you superior, it makes you a hack who can be replaced by a well-trained monkey

    I came into this industry to solve problems for people, to make people's lives better. Right now, the way to do that is to make the software more usable, not to add obscure programming concepts that only uber-geeks will ever have a use for and re-solve problems that have been solved for decades.



  • @Snooder said:

    Frankly, I feel sorry for you.
     

    That's just your elitist heart expressing the only emotion it knows.


  • ♿ (Parody)

    @blakeyrat said:

    @Snooder said:
    You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem (iteration)

    I'm pretty sure iteration has been solved already, long before C# came along. Or, phrased differently, what the holy fuck are you talking about?

    It's about lazy evaluation (which didn't wait for C# to come around). Guys, you can't rely on blakeyrat to understand anything besides that which he has actually come into contact with.

    @blakeyrat said:

    To me, novel and interesting work doesn't require the use of Fibonacci sequences.

    You probably don't even have an inkling as to how many interesting things they apply to, but that's really besides the point. These are good for any sort of, "give me the next one" sort of iteration where you aren't sure if or when you'll need the next one, especially if there's a nontrivial amount of processing involved. You don't have to do the work until it's needed. It's possible to do all of this without the generator semantics, but it's more work and you end up reinventing the wheel...badly (hence why many languages have this sort of thing).

    @blakeyrat said:

    Right now, the way to do that is to make the software more usable, not to add obscure programming concepts that only uber-geeks will ever have a use for and re-solve problems that have been solved for decades.

    Blub blub blub blub obscure blub blub blub problems blub blub blub



  • @boomzilla said:

    @blakeyrat said:
    Right now, the way to do that is to make the software more usable, not to add obscure programming concepts that only uber-geeks will ever have a use for and re-solve problems that have been solved for decades.

    Blub blub blub blub obscure blub blub blub problems blub blub blub

    To put this in terms blakeyrat still can't understand,

    Let's say you have a database with billions of rows of data. Let's say you want to do a calculation for each row in the database and return an IEnumerable of the values from the calculations. Let's also say that the calculation is more complex than what can easily be done in the database and that you have unlimited time but limited space.

    Let's compare the "equivalent" options:

    blakeyrat's list: SELECT * FROM table WHERE simple_condition;. Iterate through each item and add the calculated value to a list. Return the list. Requires O(n) time and O(n) space.

    yield: SELECT * FROM table WHERE simple_condition;. Iterate through each item and yield return the value. Requires O(n) time and O(1) space.

    So blakey, how's that infinite memory computing device coming?



  • @Ben L. said:

    Let's compare the "equivalent" options:

    blakeyrat's list: SELECT * FROM table WHERE simple_condition;. Iterate through each item and add the calculated value to a list. Return the list. Requires O(n) time and O(n) space.

    yield: SELECT * FROM table WHERE simple_condition;. Iterate through each item and yield return the value. Requires O(n) time and O(1) space.

    So blakey, how's that infinite memory computing device coming?

    You can do that without the yield, though. Easily.



  • @blakeyrat said:

    @Snooder said:
    You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem (iteration)

    I'm pretty sure iteration has been solved already, long before C# came along. Or, phrased differently, what the holy fuck are you talking about?

    @Snooder said:

    and then shit on them because you don't actually get to write anything novel or interesting in YOUR day job.

    To me, novel and interesting work doesn't require the use of Fibonacci sequences. On the contrary; I'd consider any task requiring the use of Fibonacci sequences to be tedious as hell.

     

    That was just a trivial example to show something that can be doen easily with generators that would require quite a bit more work without them.

    For an example that solves a real-world problem, have a look at Jon Skeet's Edulinq series.



  • @blakeyrat said:

    @dhromed said:
    Oh, it's some nonsense about iterators and generators for which I can't see an immediate use case, but maybe that's my disgustingly limited creative spirit?

    It just saves like 10 characters of typing. Instead of creating a list, populating it, and returning it, you can just yield each element in the list.

    Like I said above in the post nobody can read because it's invisible, I can't imagine the huge number of potential error conditions that now need to be checked on function exit (for functions that use yield) was worth the couple characters of typing it saved. But whatever.

    You don't need to check an iterator, you just iterate over it using next() which a foreach does automatically.



  • @Mason Wheeler said:

    @blakeyrat said:

    @Snooder said:
    You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem (iteration)

    I'm pretty sure iteration has been solved already, long before C# came along. Or, phrased differently, what the holy fuck are you talking about?

    @Snooder said:

    and then shit on them because you don't actually get to write anything novel or interesting in YOUR day job.

    To me, novel and interesting work doesn't require the use of Fibonacci sequences. On the contrary; I'd consider any task requiring the use of Fibonacci sequences to be tedious as hell.

     

    That was just a trivial example to show something that can be doen easily with generators that would require quite a bit more work without them.

    For an example that solves a real-world problem, have a look at Jon Skeet's Edulinq series.

    A really simple example for generators are reading lines from a file. The file might be several GB in size, but using a generator you can do a foreach loop on each line, consuming a fraction of the memory required to load the entire file and negating the need for eof checking. A more complex example of this might be to read lines until an entire paragraph is discovered then yield the entire paragraph, again only consuming as much memory is needed to hold the lines from the paragraph.



  • @blakeyrat said:

    @Ben L. said:

    Let's compare the "equivalent" options:

    blakeyrat's list: SELECT * FROM table WHERE simple_condition;. Iterate through each item and add the calculated value to a list. Return the list. Requires O(n) time and O(n) space.

    yield: SELECT * FROM table WHERE simple_condition;. Iterate through each item and yield return the value. Requires O(n) time and O(1) space.

    So blakey, how's that infinite memory computing device coming?

    You can do that without the yield, though. Easily.

    By all means, show an example.



  • @blakeyrat said:

    @Snooder said:
    You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem (iteration)

    I'm pretty sure iteration has been solved already, long before C# came along. Or, phrased differently, what the holy fuck are you talking about?

    No, it hasn't. And the fact that you think it has been solved is what makes you a hack.

    @blakeyrat said:

    @Snooder said:
    and then shit on them because you don't actually get to write anything novel or interesting in YOUR day job.

    To me, novel and interesting work doesn't require the use of Fibonacci sequences. On the contrary; I'd consider any task requiring the use of Fibonacci sequences to be tedious as hell.

    If you find math and the science of computing to be 'tedious', why the hell are you in this line of work?


    @blakeyrat said:

    @Snooder said:
    That doesn't make you superior, it makes you a hack who can be replaced by a well-trained monkey

    I came into this industry to solve problems for people, to make people's lives better. Right now, the way to do that is to make the software more usable, not to add obscure programming concepts that only uber-geeks will ever have a use for and re-solve problems that have been solved for decades.



    Again, this is the kind of thinking that makes you a hack. You don't actually have a passion for the work; for computing, for writing code or designing algorithms. You simply want to beat it into shape to do some task that you need done. Which is fine, every industry needs hacks. But don't try to parade around your contempt for the people who DO care about the work they do as if it makes you special. It doesn't.


    edit: To clarify, when I say the problem of iteration "hasn't been solved," I don't mean that there aren't ways to do what you want with existing language constructs. Any turing-complete language can do it. What I mean is that there is ALWAYS a better and more efficient way to do things. Someone who cares about computing should never settle for the status quo and should always be trying to think of ways to code better.


  • Considered Harmful

    const q = require( 'q' ),
    	XMLHttpRequest = require( 'w3c-xmlhttprequest' ).XMLHttpRequest,
    	Promise = q.Promise;
    
    function get( url ) {
    	return new Promise( function( accept, reject ) {
    		const xhr = new XMLHttpRequest;
    		xhr.onreadystatechange = function() {
    			if( xhr.readyState !== XMLHttpRequest.DONE ) return;
    
    			if( String( xhr.status ).startsWith( '2' ) ) accept( xhr.responseText );
    			else reject( xhr.status + ': ' + xhr.statusText );
    		};
    		xhr.open( 'GET', url );
    		xhr.send( null );
    	} );
    }
    
    q.spawn( function *() {
    	// this code looks synchronous but will execute asynchronously
    	const g = yield get( 'https://www.google.com/' ),
    		y = yield get( 'https://www.yahoo.com/' );
    	console.log( g );
    	console.log( y );
    } );
    

  • Discourse touched me in a no-no place

    @Snooder said:

    Here's the thing. You can't come into a forum of programmers discussing a tool intended to solve a very real and existing programming problem and then shit on them because you don't actually get to write anything novel or interesting in YOUR day job.
    Yes he can; he does it all the time.



  • @Soviut said:

    By all means, show an example.

    class DoStuff()
    List<DBRecord> records;
    
    void DoStuff(queryParamsOrWhatever)
    {
        records = ShoveDBRecordsIntoListOrTheresABillionRowsSoWhatever();
    }
    
    Result GetNextResult()
    {
        record = records.pop();
        return DoExpensiveCalculation(record);
    }


  • @blakeyrat said:

    @Soviut said:
    By all means, show an example.

    class DoStuff()
    List<DBRecord> records;
    
    void DoStuff(queryParamsOrWhatever)
    {
        records = ShoveDBRecordsIntoListOrTheresABillionRowsSoWhatever();
    }
    
    Result GetNextResult()
    {
        record = records.pop();
        return DoExpensiveCalculation(record);
    }
    // I don't know C# syntax, so have some pseudoC#
    class Wat {
        IEnumerable<Result> Stuff() {
            using (DBCursor<DBRow> cur = StartDBQuery()) {
                foreach (DBRow row in cur) {
                    yield return DoExpensiveCalculation(row);
                }
            }
        }
    }
    

Log in to reply