From: MonkeeSage Date: 2007-11-29T00:30:12+09:00 Subject: Re: Ruby needs continuations... On Nov 28, 9:19 am, MonkeeSage wrote: > On Nov 28, 6:29 am, "Just Another Victim of the Ambient Morality" > > > > wrote: > > Warning: I don't really know what I'm talking about so if I make any > > mistakes in terminology, please try to correct me... > > > I've been doing a lot of Python programming and I've discovered that > > it's actually a very powerful language. The language, itself, lacks any > > kind of elegance but it has all the power of Ruby and a little more > > performance. It also has a richer set of libraries, although not in all > > areas, surprisingly. > > One thing that Ruby should take from Python are continuations. Python > > is moving away from list creation and version 3.0 functions will return > > Python iterators, implemented with continuations, instead of actual lists, > > since they are not used nearly as much as you might think. > > The reason why I say that Ruby needs continuations is because they are > > more versatile than Ruby iterators. The reason why I say _that_ is because > > you can make Ruby iterators with continuations but you can't make > > continuations with Ruby iterators. This means that you can implement a > > continuation iterator and Object class can automatically define a Ruby > > iterator based on your continuation iterator. After all, Ruby iterators are > > nice. I'm surprised by how annoyed I am that Python for loops don't return > > a value... > > One weakness of Ruby iterators that continuations don't have is parallel > > iteration. If you have two containers that represent different aspects of > > the same things, it's difficult to iterate over both of them in Ruby. In > > Python, you can do this: > > > list1 = [1, 2, 3, 4] > > list2 = ['a', 'b', 'c', 'd'] > > > # Okay, Python is more wordy than I'd like > > # I could have just used zip() but you rarely need the list! > > for num, letter in itertools.izip(list1, list2): > > # Do something with both numbers and letters > > print num, letter > > print > > > How would one do this in Ruby? You can use .each_with_index and index > > the other list but that assumes that the other list is indexable, which only > > happens to be true of arrays but is not true in general. I've thought about > > implementing some Ruby equivalent of zip() (or preferably izip()) and > > discovered that I can't do so without continuations. > > ...Hence, my post. I'm actually at odds with Pythonic philosophy. The > > idea that there should only be one way to do things is ludicrous and a > > constant up hill battle. One thing that Python does right is that it's not > > afraid to "steal" from other languages and that's the right attitude to > > have. Adopt whatever is useful! > > Python 3.0 looks like great language. I'm hoping that Ruby 2.0 will be > > even better 'cause, frankly, Ruby is more fun to program in... > > Thank you... > > You actually need a generator, which can be implemented with > continuations, but doesn't have to be (in 1.9 the generators are > implemented with threads -- have a look at generator.rb in 1.8 and 1.9 > to see the differences). Using generators, you can implement izip (and > all of itertools if you'd like, though most of it already has > equivalent ruby solutions). Here is a pretty close translation of the > python given in the itertools docs: > > ======== > > require 'generator' > > module Enumerable > def izip(*enumerables) > enumerables = [self] + enumerables > generators = enumerables.map { | enum | > Generator.new(enum) > } > while generators[0].next? > result = generators.map { | gen | > gen.next > } > yield result > end > end > end > > [1,2,3].izip([4,5,6]) { | x, y | > puts x, y > > } > > ======== > > NB. generator.rb says that generators are slow in 1.8. > > Regards, > Jordan Ps. The SyncEnumerator class from generator does the same thing as izip: SyncEnumerator.new([1,2,3], [4,5,6]).each { | x, y | puts x, y }