4 ms·
I'm real confused about generators, but maybe I'm just missing something about what Python generators do? Like, aren't generators just a block of code that can
by RangerScience 6y ago
I'm real confused about generators, but maybe I'm just missing something about what Python generators do?
Like, aren't generators just a block of code that can produce the next value, wrapped in an iterator?
'Cuz like, sure, they're not front in center in Ruby programming and if they are in Python I can see why one language would teach you the other, but ruby blocks and yield make this pretty damn easy. So what am I missing?
- deleted 6y ago[deleted]
- mjfisher 6y agoNot a huge amount in concrete terms of capability, but the little differences add up in how the languages are used in practice. Python has functions you can refer to and pass around directly (as opposed to Ruby's blocks and procs), and that makes functions that are also generators just a little bit more friction free and more likely to be used. Python also has explicit support for differentiating between generators and regular functions in other parts of it's syntax (e.g. list comprehensions) that tend to make people reach for generators more quickly in Python than other languages.
- nerdponx 6y agoPython's lazy, composable iterators/generators are my #1 favorite Python language feature and I find myself missing it in every other language I use.
- RangerScience 6y agoMost (all?) of Rail's iterators are available as lazy iterators, and I think ditto for core Ruby (it's literally `foo.lazy.each`). Not sure what you mean by "composable" that isn't also the case in Ruby; community standard definitely seems to be that an iterator dot chain doesn't change type (or when it does it's real obvious) making it easy to `.map`, `.select`, etc.
- jcheng 6y agoRuby has generators, but it’s not just blocks and yield. Generators are special because after they’ve yielded (in the Python sense) a value, they are actually no longer on the stack at all. But when their next value is requested, they pick up execution right where they left off with all local variables intact, as if they had never suspended execution. If that doesn’t make sense to you, it’s definitely worth taking a few minutes out to look up some tutorials on generators in Python or any other language that supports them. In Ruby, you can create a generator by passing a block to Enumerator#new; the block’s parameter is a “yielder” object whose << operator behaves like Python’s yield keyword. Keep in mind that this block is NOT invoked once per iteration; it is invoked once, it might suspend and resume though (or suspend and not resume!). https://stackoverflow.com/questions/35826375/enumerator-new-and-yield https://stackoverflow.com/questions/35826375/enumerator-new-...
- jonnytran 6y agoYes, the difference is between internal iterators vs. external iterators. For external iterators, Ruby's Enumerator syntax is a little less convenient. But I think it's a small price to pay for not having 2 colors of functions [1]. In Ruby, an Enumerator is just an object with methods like any other object. And there are things built in to core to make working with lazy enumerators just as easy as regular ones. To GP's point, you rarely actually need enumerators because of a block's ability to break in Ruby. It's the most useful thing that's in so few languages [2]. For example, if I really wanted to write an infinite loop yielding fib -- not saying I would do it this way but -- the quickest way to do it in Ruby, adapting the Stack Overflow example, is probably more like this: def fib() puts "Enter function" a = b = 1 i = 0 loop do puts "Inside loop" yield i, a puts "i: #{i}, a: #{a}, b: #{b}" a, b = b, a + b i += 1 end end n_from_user_input = 5 fib do |i, x| break if i == n_from_user_input puts "Use value: #{x}" end 1: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-... 2: https://yehudakatz.com/2012/01/10/javascript-needs-blocks/ https://yehudakatz.com/2012/01/10/javascript-needs-blocks/