Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Ruby blocks in Python, a suggestion

Reply
Thread Tools

Ruby blocks in Python, a suggestion

 
 
Lonnie Princehouse
Guest
Posts: n/a
 
      04-14-2004
Joe Mason <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
>
> I still don't see the advantage over
>
> def test():
> def my_func(x, y):
> assert(y == x * 2)
>
> for (x, y) in [(1,2), (2,4), (3,6)]:
> my_func(x, y)
>


In this particular example, there's no advantage to using codeblocks
over functions. However, dynamically scoped blocks would facilitate a
range of things that are difficult to do with functions, particularly
in the metaprogramming arena. If you're trying to write code that
writes code, it's really handy to have blocks that execute in the
current scope instead of in a new one.

If dynamically scoped blocks were added to the language, it would give
metaprogrammers a much cleaner syntax that could replace a lot of
exec, eval, and compile calls, not to mention it would reduce the need
to tinker directly with frames.

.... Speaking of which, it's too bad that Glenn's sys._getframe() hack
doesn't quite work. Can anybody figure a way to inject locals created
these "blocks" back into the calling frame's locals? Illustration of
the problem-

class block:
def __init__(self, f):
self.f = f
def __call__(self):
import sys
exec self.f.func_code in sys._getframe(1).f_locals

def next_fibonacci_term():
fibonacci_sequence.append(fibonacci_sequence[-2] +
fibonacci_sequence[-1])
i = len(fibonacci_sequence) - 1

nft_block = block(next_fibonacci_term)

fibonacci_sequence = [0,1]

[nft_block() for n in range(20)]

print fibonacci_sequence
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987,
1597, 2584, 4181, 6765, 10946]

print i
# Traceback (most recent call last):
# File "<stdin>", line 1, in ?
# NameError: name 'i' is not defined

Conclusion-
"exec foo in scope" appears to execute foo in a _copy_ of scope, s.t.
we can modify objects that are contained in the scope, but assignment
won't work.
 
Reply With Quote
 
 
 
 
Joe Mason
Guest
Posts: n/a
 
      04-14-2004
In article <(E-Mail Removed)>, Ville Vainio wrote:
>>>>>> "Joe" == Joe Mason <(E-Mail Removed)> writes:

>
> Joe> I still don't see the advantage over
>
> Joe> def test():
> Joe> def my_func(x, y):
> Joe> assert(y == x * 2)
>
> Joe> for (x, y) in [(1,2), (2,4), (3,6)]:
> Joe> my_func(x, y)
>
> Joe> With more parameters it'd be more convenient, but also much
> Joe> easier to be sloppy.
>
> Add z = 10 to the would-be block my_func, and you'll see the
> difference. With statically scoped block semantics (instead of
> function semantics), it would bind z as a local variable in test,
> instead of local variable in my_func. It's not possible with functions
> currently, because binding it in my_func makes it a local variable in
> my_func.


Yes, it would. I consider that a bad thing, because now if I add a new
variable before and after the "block call", the block can fiddle with
it accidentally. If the block's in-line this isn't (as much of) a
problem since it's easy to scan.

If you actually want to update the value of z in the block, what's wrong
with this?

def test():
def my_func(x, y, z):
assert(y == x * 2)
z = 10
return z

for (x, y) in [(1, 2), (2, 4), (3, 6)]:
z = my_func(x, y, z)

(Of course, passing z to my_func and then not using it doesn't make much
sense, but maybe it's just leaving it open for expansion.

Joe
 
Reply With Quote
 
 
 
 
Joe Mason
Guest
Posts: n/a
 
      04-14-2004
In article <(E-Mail Removed) >, Lonnie Princehouse wrote:
> In this particular example, there's no advantage to using codeblocks
> over functions. However, dynamically scoped blocks would facilitate a
> range of things that are difficult to do with functions, particularly
> in the metaprogramming arena. If you're trying to write code that
> writes code, it's really handy to have blocks that execute in the
> current scope instead of in a new one.
>
> If dynamically scoped blocks were added to the language, it would give
> metaprogrammers a much cleaner syntax that could replace a lot of
> exec, eval, and compile calls, not to mention it would reduce the need
> to tinker directly with frames.


Now that I can buy. I'd prefer to add explicit metaprogramming-support
facilities than a generic "block" construct, though.

Joe
 
Reply With Quote
 
Hung Jung Lu
Guest
Posts: n/a
 
      04-15-2004
http://www.velocityreviews.com/forums/(E-Mail Removed) (Lonnie Princehouse) wrote in message news:<(E-Mail Removed). com>...
>
> def next_fibonacci_term():
> fibonacci_sequence.append(fibonacci_sequence[-2] +
> fibonacci_sequence[-1])
> i = len(fibonacci_sequence) - 1
>
> nft_block = block(next_fibonacci_term)
>
> fibonacci_sequence = [0,1]
>
> [nft_block() for n in range(20)]
>
> print fibonacci_sequence
> # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987,
> 1597, 2584, 4181, 6765, 10946]
>
> print i
> # Traceback (most recent call last):
> # File "<stdin>", line 1, in ?
> # NameError: name 'i' is not defined
>
> Conclusion-
> "exec foo in scope" appears to execute foo in a _copy_ of scope, s.t.
> we can modify objects that are contained in the scope, but assignment
> won't work.

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

Run-time codeblocks DO ALREADY EXIST in Python, via the compile()
function. So we are basically talking about the need for COMPILE-TIME
codeblocks.

Python run-time codeblocks are fully functional. Before making any
comment/question about codeblocks in Python, the first thing is to
check it with the compile() function. (Questions may include: Can you
assign to local variables? Can you assign to global variables? Can you
have break/continue statements in codeblocks? etc. etc.)

#------------------------------------------------
nft_block = compile('''

fibonacci_sequence.append(
fibonacci_sequence[-2] + fibonacci_sequence[-1])
i = len(fibonacci_sequence) - 1

''', '<string>', 'exec')

fibonacci_sequence = [0, 1]
for n in range(20):
exec nft_block

print fibonacci_sequence
# [0, 1, ..., 10946]

print i
# 21
#------------------------------------------------

The compile() approach has a scope problem, too. That is, when used
inside functions, it won't bind to global variables automatically. But
one can always use the 'global' statement explicitly inside the
codeblock, if necessary. The compile() function is not a new thing. It
has been battle-tested from early days of Python. It's just an
inconceivable mistake that Python does not port the run-time codeblock
into compile-time.

regards,

Hung Jung
 
Reply With Quote
 
Lonnie Princehouse
Guest
Posts: n/a
 
      04-15-2004
(E-Mail Removed) (Hung Jung Lu) wrote in message news:<(E-Mail Removed). com>...
>
> Run-time codeblocks DO ALREADY EXIST in Python, via the compile()
> function. So we are basically talking about the need for COMPILE-TIME
> codeblocks.
>


True =) Guess I was a little carried away with trying to fake
compile-time codeblocks. It just seems so kludgy, having to write
code in a string...



# 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
 
Reply With Quote
 
Lonnie Princehouse
Guest
Posts: n/a
 
      04-15-2004
(my apologies if this message appears more than once... mozilla is
behaving strangely)

(E-Mail Removed) (Hung Jung Lu) wrote in message news:<(E-Mail Removed). com>...
>
> Run-time codeblocks DO ALREADY EXIST in Python, via the compile()
> function. So we are basically talking about the need for COMPILE-TIME
> codeblocks.
>


True =) Guess I was a little carried away with trying to fake
compile-time codeblocks. It just seems so kludgy, having to write
code in a string...



# 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
 
Reply With Quote
 
Hung Jung Lu
Guest
Posts: n/a
 
      04-16-2004
(E-Mail Removed) (Lonnie Princehouse) wrote in message news:<(E-Mail Removed). 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
 
Reply With Quote
 
Michele Simionato
Guest
Posts: n/a
 
      04-17-2004
(E-Mail Removed) (Hung Jung Lu) wrote in message news:<(E-Mail Removed). 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Methods and blocks - not that clear when blocks passed into Steven Taylor Ruby 9 04-27-2009 08:46 AM
Coexistency Problem: cygwin + Ruby for Window (and suggestion for improving the Ruby installer) Ronald Fischer Ruby 6 05-21-2007 08:32 AM
"Building Blocks" are "Application Blocks" Arjen ASP .Net 3 02-27-2005 01:06 AM
procs/blocks - blocks with procs, blocks with blocks? matt Ruby 1 08-06-2004 01:33 AM



Advertisments