473,320 Members | 1,940 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Ruby blocks in Python, a suggestion

I participated in a short thread on c.l.ruby, and had myself convinced
that "blocks" might be a good idea. For bragging rights, if nothing
else :).

What I'm talking about is:

<callable> block [<block args>]:
suite
<callable> would be called with one argument, 'block', which it could
execute via normal calling (or call, or execute, or whatever).

i.e.

class with_open_file:
def __init__(self, *args):
self.args = args
def __call__(self, block):
f = open(*self.args)
try:
block.call(f) # f is passed to the "block argument"
finally:
f.close()

def somefunc():
x = 10
with_open_file("a.txt","r") block(f): # assigns f to the opened file
x = len(f.read()) # rebinds x!

Note that block would be executed with the same bindings as
somefunc(), not its lexically closed bindings that would be the case
if the actions within block were in a normal function.

Other examples:

transaction(dbconn) block(t): # commit/rollback t based on exception status
t.dostuff()
foreach([(1,2), (2,4), (3,6)]) block(x,y):
assert y == X*2

mapseq(seq) block(entry, result):
result.append(entry * 2)

Obviously this functionality could be quickly hacked by making the
bindings of "block parameters" function-global just like the variable
in for loops (and LC's in the current implementation). Even if only
block-visible fucntionality would be so much cooler.

And yes, I know this blocks issue has been hashed over previously. I'm
just too busy to google for it right now, and just wanted to get this
off my chest quickly :-).

--
Ville Vainio http://tinyurl.com/2prnb
Jul 18 '05 #1
5 1525
I'm not convinced this will fly.

First, of your examples, two are better expressed as loops or listcomps:

foreach([(1,2), (2,4), (3,6)]) block(x,y):
assert y == X*2 for x, y in [(1,2), (2,4), (3, 6)]:
assert y == x*2
mapseq(seq) block(entry, result):
result.append(entry * 2)
result += [entry*2 for entry in seq]

Every block that is executed N times should be expressed today as a
"for" loop or listcomp with the appropriate generator.

transaction(dbconn) block(t): # commit/rollback t based on exception status
t.dostuff()


I would swear there was a pep for a "with" statement, taking an object
with special methods called at the top and the bottom of the statement.
I can't find it, though. It would look something like this:
t = transaction(dbconn)
with transaction(dbconn):
t.dostuff()

Eery block that is executed exactly 1 time should be expressed today as
t.acquire()
try:
block
finally:
t.release()
or
t.acquire()
try:
block
except:
t.rollback()
raise
else:
t.commit()
The second problem is that I don't know if the Python parser can
accomodate your syntax. Your proposal doesn't mention the exact
production(s) you would add or change to add your block statement.

One way would be to make compound_stmt include a block_stmt alternative
compound_stmt: block_stmt | if_stmt | ...
block_stmt: test 'block' ['(' arglist ')'] ':' suite
can you tell me if this is the way you imagined defining the new rule,
and show me that this does not create a conflicting or ambiguous
grammar? (the fact that Python prints "XXX ambiguity!" over and over
again when I try to build the modified grammar doesn't bode well, but
maybe it's just been too long since I toyed with the Python grammar..)

Finally, what do "break" and "continue" do in blocks?

Jeff

Jul 18 '05 #2
"Ville Vainio" <vi***@spammers.com> wrote in message
news:du*************@lehtori.cc.tut.fi...
I participated in a short thread on c.l.ruby, and had myself convinced
that "blocks" might be a good idea. For bragging rights, if nothing
else :).


Ruby's blocks are part of a larger feature that most Ruby
afficianados think is well worth the price of admission.

The typical use of a block in Ruby is to inject some code
into a predefined routine. The code will be executed with
a yield statement. In general, that block has access to the
routine's variables, and vice versa. The routine is normally
some kind of loop over a collection. The block itself is
placed after the calling parameter list.

After a lot of pondering, I think that it wouldn't be that hard
to add anonomous functions to Python, but without the other
features it would be somewhat less than overwhelmingly
useful, as it is in Ruby.

A lot of people have tried to get a nice syntax over the years,
and have failed to find anything persuasive. So I conclude that
there isn't a "nice" syntax that will get universal acclaim.
Therefore, the following will work, and might even be
relatively easy to implement.

foobar = {def (...):
suite
}

The trick is that on encountering the opening brace the current
indentation environment is suspended (stacked) and a new
indentation environment is created. The left boundary of the
new environment is the first non white-space character on the
next non-comment line. The new indentation environment is
released when the closing brace is encountered, and the prior
one is reinstated.

I'd like this form of function definition for interactive fiction (IF)
games, since it allows me to create a function and put it into
an instance with one operation, rather than having to create
the function at the module level, and then bind it into the instance
with another function call after the definition is complete.

John Roth
Jul 18 '05 #3
Ville Vainio <vi***@spammers.com> wrote in message news:<du*************@lehtori.cc.tut.fi>...
I participated in a short thread on c.l.ruby, and had myself convinced
that "blocks" might be a good idea. For bragging rights, if nothing
else :).
...
foreach([(1,2), (2,4), (3,6)]) block(x,y):
assert y == X*2


Ruby's block is quite a bizarre animal. It's amazing how people can
make a big mess out of something so simple and so fundamental. A more
useful concept is plain-vanilla codeblock. I have mentioned before
syntax like:

def my_codeblock:
assert(y == x*2)

for (x,y) in [(1,2), (2,4), (3,6)]:
exec my_codeblock

Which you actually can do in Python, if you replace the def statement
with:

my_codeblock = compile('assert(y == x*2)', '<string>', 'exec')

------------------

Python's lack of compile-time, easily-debuggable codeblock is one of
the obvious major shortcomings/mistakes of the language. Codeblocks
are absolutely wonderful for metaprogramming, to the point of being
essential. This topic has been discussed before, and I am not going
back there. When people are short-sighted, there is no cure. :) Other
people can take over the issue.

regards,

Hung Jung
Jul 18 '05 #4
fn***@u.washington.edu (Lonnie Princehouse) wrote in message news:<f7**************************@posting.google. com>...

# But now it's an idee fixe. Here we go again!
import inspect, re

def block(f):
# won't work from stdin, function code must be in a file
# decompyle could help?
source = inspect.getsource(f)
source = source[source.index('\n')+1:]
indent = re.search('^(\s+)\S',source).group(1)
source = re.sub('(?m)^%s' % indent, '', source)
return compile(source, '<string>', 'exec')

def my_codeblock():
z = x + y

my_codeblock = block(my_codeblock)

for (x,y) in [(1,2), (2,4), (3,6)]:
exec my_codeblock


Man, it's a hack all right, but what a brilliant one! :) Never ever
seen anyone coming up with it.

Sure, it's not debuggable in the sense that you can't place break
points, and when there is an exception you won't see the exact line.
However, this part can be solved by generating small files in the
block() function, one per codeblock. Then, instead of '<string>', pass
the file name. Not only you will be able to see the line where error
happened, but you will also be able to put break points, or to step
through the code lines. The only thing to remember is to know where
you need to make the changes: not in the codeblock files, but in the
original place of definition. :) This can be helped by pre-pending
some explanatory messages in the codeblock files (pointing out the
location of the original file, i.e., via inspect.getsourcefile() and
inspect.getsourcefilelines()). Of course, in shipped products you'll
suppress the generation of the codeblock files.

It's functional. It's usable. It's compiler-checked. The refined
version should be published as a recipe!

Man! Wow! Triple Wow!

regards,

Hung Jung
Jul 18 '05 #5
hu********@yahoo.com (Hung Jung Lu) wrote in message news:<8e**************************@posting.google. com>...
Python's lack of compile-time, easily-debuggable codeblock is one of
the obvious major shortcomings/mistakes of the language.
Why ??
Codeblocks are absolutely wonderful for metaprogramming, to the point of
being essential.
Why ??
This topic has been discussed before, and I am not going
back there. When people are short-sighted, there is no cure. :) Other
people can take over the issue.


I have not followed in detail your discussion about code blocks, scattered
in different threads in different times, so please point out to me the posts
where your substain your claims.

My experience with code blocks has been the following:

1. At least one year ago I discovered on my own that Python has already
run time code blocks.

2. More or less at the same time I discovered the hack proposed by
Lonnie Princehouse which I used to implement macros in Python as
a proof of concept.

3. I didn't find any compelling use case for both 1 and 2; actually I
thought they were confusing and un-needed constructs, so after having
implemented them, I forgot them.

I may have been wrong about point 3. If so, please tell me why.
Otherwise, please stop making unsubstained claims and give
explanations and/or references to previous posts.
Michele Simionato
Jul 18 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

220
by: Brandon J. Van Every | last post by:
What's better about Ruby than Python? I'm sure there's something. What is it? This is not a troll. I'm language shopping and I want people's answers. I don't know beans about Ruby or have...
54
by: Brandon J. Van Every | last post by:
I'm realizing I didn't frame my question well. What's ***TOTALLY COMPELLING*** about Ruby over Python? What makes you jump up in your chair and scream "Wow! Ruby has *that*? That is SO...
30
by: Christian Seberino | last post by:
How does Ruby compare to Python?? How good is DESIGN of Ruby compared to Python? Python's design is godly. I'm wondering if Ruby's is godly too. I've heard it has solid OOP design but then...
5
by: F Jamitzky | last post by:
It is rather easy to define functions in python that mimic the special ruby syntactic sugar like: 5.times { print "Hello World!" } or .each { |food| eat food } In python these fragments...
77
by: Hunn E. Balsiche | last post by:
in term of its OO features, syntax consistencies, ease of use, and their development progress. I have not use python but heard about it quite often; and ruby, is it mature enough to be use for...
22
by: Francois | last post by:
I discovered Python a few months ago and soon decided to invest time in learning it well. While surfing the net for Python, I also saw the hype over Ruby and tried to find out more about it, before...
26
by: brenocon | last post by:
Hi all -- Compared to the Python I know and love, Ruby isn't quite the same. However, it has at least one terrific feature: "blocks". Whereas in Python a "block" is just several lines of...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.