python contextmanagers and ruby blocks

A

Alia Khouri

As an exercise, I recently translated one of my python scripts (http://
code.activestate.com/recipes/576643/) to haskell (a penultimate
version exists at http://groups.google.com/group/comp.lang.haskell/browse_thread/thread/fb1ebd986b44244e#
in case anyone is interested) with the result that haskell has now
become my second favourite language (after python of course :)

Just to change mental gears a bit, I'd now like to do the same and
create a ruby version. As I've progressed on the latter, I've been
struck by how pervasive the use of blocks is in ruby. For example:

class Builder
attr_accessor :name
def machine &block
@name = "m1"
block.call
end

def build(x, &block)
puts x
block.call
end
end

builder = Builder.new

builder.machine do
puts "hello #{builder.name}"
end

builder.build "hello" do
puts "world"
end

which should print out:
hello m1
hello
world

Now, python's relatively new contextmanagers seem to provide something
similar such that one can write:

from __future__ import with_statement
from contextlib import contextmanager

class Builder:
@contextmanager
def machine(self):
self.name = "m1"
yield

@contextmanager
def build(self, x):
print x
yield

builder = Builder()

with builder.machine():
print 'hello %s' % builder.name

with builder.build("hello"):
print 'world'

Which brings me to my questions:

1. To what extent are python's contextmanagers similar or equivalent
to ruby's blocks?

2. If there is a gap in power or expressiveness in python's context
managers relative to ruby's blocks, what are possible (syntactic and
non-syntactic) proposals to bridge this gap?

Thank you for your responses.

AK
 
A

Alia K

Francesco said:
... ruby code that shows the most twisted 'Hellow world' example I have
ever seen :) ...

and I was gunning for the simplest possible example (-:

... python code doing the same thing - apparently -
of prevous ruby code, using context managers in a way that I believe the
authors of contextlib module never thought of.

Methinks they probably thought of such usage.
ASAIK, context managers are nothing like ruby blocks.
Context managers have a very specific purpose : to make people able to
abstract the code that one writes to 'enter a context'
(i.e. open a file, start a transaction, ... ) and 'leave a context'
(i.e. close a file, commit or rollback the transaction ... ).
So that you can separate context handling code from the code that performs
actions insed that context, factoring out the first for reuse and better
code maintenance.

Thinking about it: I suppose one could say in python a contextmanager
defines the functional context of a block of code and makes it a first
class construct in the language, whereas in ruby the block itself is a
first class citizen -- contextmanagers are like the inverse of blocks.
Ruby blocks are blocks of code which can be passed as
objects for a number of different usage - for instance to make context
management stuff. If I have to compare them to something in Python, I
would say they are 'lambda on steroids' or 'nameless functions'.

Agreed, but also they are more tightly integrated e.g. the &block
construct which can be passed into functions...
personally - I don't like them just as I don't like lambdas in python for
anything but one-liners and I don't like anonymous functions in haskell
(which I am painfully trying to learn ). They may be cool to write, but
they look not very readable to me - but maybe this is just me.

In case you are learning haskell, here are some excellent guides
(order is important) :

* Learn you a haskell: http://learnyouahaskell.com/chapters
* Real World Haskell: http://book.realworldhaskell.org/
* Typeclassopedia: http://byorgey.wordpress.com/2009/02/16/the-typeclassopedia-request-for-feedback/

(I'm personally still scratching the surface of it all...)

back to the subject...

I suppose because contextmanagers (indeed decorators) are so
relatively new to python, it will probably take a little while for
these constructs to comprehensively penetrate the stdlib. It's already
happened with files, locks, and db transactions but I'm sure there are
many instances where one could benefit from using the with statement.

Nevertheless, I remain curious about whether once can use the
contextmanager in python to achieve the full power of ruby's blocks...

Best,

AK
 
A

Aahz

Nevertheless, I remain curious about whether once can use the
contextmanager in python to achieve the full power of ruby's blocks...

Short answer: no

Longer answer: the way in Python to achieve the full power of Ruby
blocks is to write a function.
 
A

Alia K

Aahz said:
Longer answer: the way in Python to achieve the full power of Ruby
blocks is to write a function.

You are most likely right... there is probably no need to introduce
ruby-like blocks to python where iteration comes naturally with list
comprehensions and generators. But for the simple case of entering a
block of code as one does with @contextmanager I suppose it would be
nice to make a generator with a single yield statement a
contextmanager by default such that:
.... print "a"
.... yield
.... print "b"
........ print "c"
....
a
c
b

would be equivalent to
.... def g():
.... print "a"
.... yield
.... print "b"
........ print "c"
....
a
c
b

but then again, I suppose "explicit is better than implicit"...

AK
 
A

Aahz

Aahz said:
Longer answer: the way in Python to achieve the full power of Ruby
blocks is to write a function.

You are most likely right... there is probably no need to introduce
ruby-like blocks to python where iteration comes naturally with list
comprehensions and generators. But for the simple case of entering a
block of code as one does with @contextmanager I suppose it would be
nice to make a generator with a single yield statement a
contextmanager by default such that [...]

There has been some discussion of this on the python-ideas mailing list;
if this is a subject you care about, you may want to read up on the
history and join the list.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top