hoodwink.d enhanced


Holy Red Snakes! #

by why in inspect

Gabriele Renzi wrote in about Guido van Rossum’s PEP #340 Anonymous Block Statements proposal announced today:

Think of PEPs as RCRs in python land. Notice this has just been written and is probably going to change a whole lot, but the core idea is: adding blocks to python.

Notice the great near-to-end phrase: Note: the syntactic extensions to yield make it use very similar to that in Ruby. This is intentional.

I can’t seem to find practical examples, but it appears that the block..as is the influenced syntax here:

 block with_file(filename) as f:
   for line in f:
     print process(line)

The above being the example of the non-looping case, much like we use File.open with a block that closes our file handles. And you can use yield inside the with_file definition very much like you do in Ruby.

About Ruby’s influence, Guido says:

I think we’re on to something. And I’m not too proud to say that Ruby has led the way here to some extent (even if Python’s implementation would be fundamentally different, since it’s based on generators, which has some different possibilities and precludes some Ruby patterns.)

Of course. Ahem. You’re all red. All of you.

said on 27 Apr 2005 at 17:40

Note: the syntactic extensions to yield make it use very similar to that in Ruby. This is intentional.

They finally got it. The snakes finally figured out that anonymous blocks are what sets Ruby apart from Python and allows you to do all sorts of cool things in Ruby that can’t be done (as easily) in Python. For years the snake people have been repeating the mantra that there’s nothing you can do in Ruby that can’t be done in Python.

Well, we’ll still have the sky punchers.

But how does this match with Guido’s intention to get rid of lambda’s in an upcoming version of Python? Seems to be a bit of a contradiction. Also, will python’s proposed anonymous blocks allow for more than one statement? Stay tuned. For now I don’t think we’ll lose any Rubyists to the Snake.

said on 27 Apr 2005 at 20:56

And when will Ruby get Python’s list comprehensions? I think this is one of the biggest downsides of Ruby. I dare anyone to write the second line of the code shown in this page in Ruby as elegantly as the Python version.

said on 27 Apr 2005 at 22:46


indexes = [[letters[i] for letters in buttons] for i in range(3)]

As a non-Python programmer, I find the above to be almost unreadable, and much prefer the Ruby map style.

If you’re still interested in list comprehensions for Ruby, someone wrote a short implementation of them once. See somewhere on ruby-talk.

said on 27 Apr 2005 at 22:48

Sorry, Array.new(3) {|i| buttons.collect {|button| button[i].chr}} is the best I can do, but my powers are weak.

said on 27 Apr 2005 at 22:58

P.S If you want to match line length to the Python version, [i].chr can be replaced with the not as understandable [i, 1]. If you want.

P.P.S If you want even less line length, collect’s alias, map, could be used.

said on 27 Apr 2005 at 23:09

Sorry, I got ahead of myself with the P.S above. Matching line length requires map.

said on 28 Apr 2005 at 03:00
indexes = [[letters[i] for letters in buttons] for i in range(3)]
indexes = (0..2).map{|i| buttons.map{|button| b[i].chr}}

The solution in Ruby can be read left-to-right, Python’s requires one to parse the whole expr. to find the indices used in the iteration. It is arguably easier to remember the indices than the expression being evaluated.

There are some things one can express more easily with list comprehensions. The above is not one of them. Better luck next time, lesbo.

said on 28 Apr 2005 at 04:33

I’d have found more interesting an example of a list comprehension using mapping and filtering. Not really harder to do in ruby (see map_filter on the wiki) but at least not builtin :)

said on 09 May 2005 at 12:56

Another option:

buttons.map{|button| button[0..2].scan(/./)}.transpose

I love Ruby.

said on 11 May 2005 at 12:07

Here are some more Python variants for that code.

>>> buttons = ["abc", "def", "ghi"]
>>> zip(*buttons)[:3]
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]
>>> zip(*[s[:3] for s in buttons])
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]
>>> from itertools import islice, izip 
>>> list(islice(izip(*buttons), 3))
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]

The first works best for the original purpose. The latter two are increasingly more memory efficient. This isn’t a case where list comps shine.

said on 11 May 2005 at 12:09

Sorry about the > (or should I write >? or >?) The preview button appears to use different escaping rules than the submit.

Comments are closed for this entry.