3 ms·
Hah, as a Pythonista, I'd say it was definitely written by a Rubyist :D That initial example would usually be, in Python: class Stuff: def __init__(self
by necovek 5y ago
Hah, as a Pythonista, I'd say it was definitely written by a Rubyist :D
That initial example would usually be, in Python:
class Stuff:
def __init__(self):
self.a_list = [1,2,3,4]
def __iter__(self):
for value in self.a_list:
yield value
Basically, iterators and generators are native constructs that for loop operates on in Python (lists, which are actual "data", are simply special-case optimized instances of those).
Instead of calling iterators/generators "data", I'd call them wrapper control-flow constructs that `for` really operates on which provide amazing syntactic power in Python.
Ruby, from the examples given, seems quite similar, except that the "syntactic sugar" is somewhat inverted. I don't think it makes for a huge difference, but I don't have any Ruby experience.
- softwaredoug 5y agoAuthor here, I think this would have made the post better for sure, especially to contrast how `yield` does the opposite thing in each language
- jonahx 5y agoThe article has some misunderstandings about idiomatic ruby imo. > Ruby keeps going with its methods-first approach, except instead of each we have a new set of methods commonly implemented on collections, as below: And then you show map, select, etc being re-implemented. But once you have "each" defined, you'd just include "Enumerable" and get all the others for free. As a separate point, I almost never implement each on a custom object in ruby. There are probably "library code" cases where it's appropriate, but in day to day work it should be rare. Typically I'd put objects in an ordinary array instead. Nit: Ruby style guide (and most experienced code I've seen) never uses parens to invoke a method with no args.
- JohnBooty 5y agoAs a separate point, I almost never implement each on a custom object in ruby. There are probably "library code" cases where it's appropriate Likewise. I've worked with Ruby fulltime since 2014 and never done it in actual project code, only in book exercises, and I'm not sure I've seen it in any gems I've dove into, though I've never poked around in ActiveRecord. Like you said, I can't think of too many reasons why one would want to implement #each -- on a daily basis I'm just putting various objects into arrays, hashes, etc. I tend to write very "boring" Ruby. Ruby gives you lots of ways to get wacky, but IMO the default best practice would be to keep it simple and avoid the cute stuff unless you really have a reason.
- danudey 5y agoOr, in Python 3.3 and above: class Stuff: def __init__(self): self.a_list = [1,2,3,4] def __iter__(self): yield from self.a_list
- remram 5y agoCan't you just: def __iter__(self): return iter(self.a_list)
- necovek 5y agoI was not trying to go for the shortest code, but to show idiomatic code where you could easily do something else instead of just returning same values (otherwise, there is no value in wrapping a list with a class at all). With both `iter(self.a_list)` or `yield from` you'd have to add a list comprehension in there to process each element, and with no Ruby-like blocks in Python, that limits what one can do. But they are both definitely good approaches to highlight!
- remram 5y agoYou mean generator, not list comprehension. Either way, you wouldn't `yield from` a list comprehension, you'd just use a loop. E.g. why write: yield from (a*2 for a in self.a_list) When you can: for a in self.a_list: yield a*2
- necovek 5y agoExactly, that's the reason I used a loop in the original snippet :)