Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Re: syntax for code blocks

Reply
Thread Tools

Re: syntax for code blocks

 
 
Peter Pearson
Guest
Posts: n/a
 
      04-29-2012
On Fri, 27 Apr 2012 13:24:35 +0200, Kiuhnm <kiuhnm03.4t.yahoo.it> wrote:
> I'd like to change the syntax of my module 'codeblocks' to make it more
> pythonic.
>
> Current Syntax:
>
> with res << func(arg1) << 'x, y':
> print(x, y)
>
> with res << func(arg1) << block_name << 'x, y':
> print(x, y)
>
> New Syntax:
>
> with res == func(arg1) .taking_block (x, y):
> print(x, y)
>
> with res == func(arg1) .taking_block (x, y) as block_name:
> print(x, y)

[snip]

Hey, guys, am I the only one here who can't even guess what
this code does? When did Python become so obscure?

--
To email me, substitute nowhere->spamcop, invalid->net.
 
Reply With Quote
 
 
 
 
mwilson@the-wire.com
Guest
Posts: n/a
 
      04-30-2012
Ben Finney wrote:

> [ ... ] Even worse is the
> penchant for ‘foo .bar()’, the space obscures the fact that this is
> attribute access.


I like the style sometimes when it helps to break the significantly different parts out of
boilerplate:

libbnem. BN_add .argtypes = [ctypes.POINTER (BignumType), ctypes.POINTER (BignumType),
ctypes.POINTER (BignumType)]
libbnem. BN_add .restype = ctypes.c_int
libbnem. BN_add_word .argtypes = [ctypes.POINTER (BignumType), ctypes.c_ulong]
libbnem. BN_add_word .restype = ctypes.c_int

libbnem. BN_sub .argtypes = [ctypes.POINTER (BignumType), ctypes.POINTER (BignumType),
ctypes.POINTER (BignumType)]
libbnem. BN_sub .restype = ctypes.c_int
libbnem. BN_sub_word .argtypes = [ctypes.POINTER (BignumType), ctypes.c_ulong]
libbnem. BN_sub_word .restype = ctypes.c_int

(there were a lot more in the original program where those came from.) Another take-away
might be don't use boilerplate, but in the situation I didn't see a simple way to avoid it.

Mel.
 
Reply With Quote
 
 
 
 
mwilson@the-wire.com
Guest
Posts: n/a
 
      04-30-2012
> On 4/30/2012 17:02, Kiuhnm wrote:
>> BignumTypePtr = ctypes.POINTER(BignumType)
>>
>> for op, op_word in ((libbnem.BN_add, libbnem.BN_add_word),
>> (libbnem.BN_sub, libbnem.BN_sub_word)):
>> op.argtypes = [BignumTypePtr] * 3
>> op_word.argtypes = [BignumTypePtr, ctypes.c_ulong]
>> op.restype = op_word.restype = ctypes.c_int

>
> On second thought, BignumPtrType is probably the right name.


(Way off the original topic, aren't we?) I haven't looked inside ctypes,
and don't know what kind of thing ctypes.POINTER actually constructs. I was
worried about falling into a [[a]]*3 kind of error -- unwittingly sharing a
mutable object. I guess I really should look.

Mel.

 
Reply With Quote
 
mwilson@the-wire.com
Guest
Posts: n/a
 
      04-30-2012
Kiuhnm wrote:
> Regarding ctypes, try this to convince yourself that there's no problem
> in reusing BignumPtrType:
> from ctypes import POINTER, c_int
> assert POINTER(c_int) is POINTER(c_int)


print ('POINTERs are shareable:', ctypes.POINTER (BignumType) is ctypes.POINTER
(BignumType))
[ ... ]
('POINTERs are shareable:', True)

Thanks.
Mel.

 
Reply With Quote
 
alex23
Guest
Posts: n/a
 
      05-01-2012
On Apr 30, 2:05*am, Peter Pearson <ppear...@nowhere.invalid> wrote:
> Hey, guys, am I the only one here who can't even guess what
> this code does? *When did Python become so obscure?


Thankfully it hasn't. The most Pythonic way to pass around a code
block is still to use a function.

 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      05-01-2012
On Tue, 01 May 2012 16:18:03 +0200, Kiuhnm wrote:

> "Most Pythonic" doesn't mean better, unfortunately.


Perhaps. But this example is not one of those cases.


> For instance, assume that you want to write a function that accepts a
> dictionary of callbacks:
> func(some_args, callbacks)
>
> Pythonic way
> ------------
>
> def when_odd(n):
> pass

[snip multiple function definitions]

> func(some_args, {'when_odd' : when_odd,
> 'when_prime' : when_prime,
> 'before_check' : before_check,
> 'after_check' : after_check})


> My way
> ------
>
> with func(some_args) << ':dict':
> with when_odd as 'n':
> pass
> with when_prime as 'n':
> pass



If you actually try that, you will see that it cannot work. You get:

SyntaxError: can't assign to literal


Have you actually tried to use these code blocks of yours? I asked you
for a *working* example earlier, and you replied with examples that
failed with multiple NameErrors and no hint as to how to fix them. And
now you give an example that fails with SyntaxError. I'm reluctantly
coming to the conclusion that these "code blocks" of yours simply do not
work.


> with before_check as '':
> pass
> with after_check as '':
> pass


You have a bug in one or more of those callbacks.

Of course you do -- all non-trivial software has bugs. The question is,
how are you going to find it? You can't unit-test the individual
callbacks, because they don't exist in a form that can be tested.

So in this case, even though Python is slightly more verbose, and forces
you to have the discipline of writing named functions ahead of time, this
is actually a *good* thing because it encourages you to test them.

If the callbacks are trivial functions, the Pythonic way is to use
lambdas:

func(some_args, {'when_odd': lambda n: n-1,
'when_prime': lambda n: n**2 - 1,
...})

although I would discourage that unless they are *really* trivial. But
for callbacks of any complexity, they will need to be tested, otherwise
how do you know they do what you want them to do?

Your code blocks make unit testing of the callbacks impossible, and for
that reason the Pythonic way is better.


--
Steven
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      05-02-2012
On Tue, 01 May 2012 19:07:58 +0200, Kiuhnm wrote:

> On 5/1/2012 17:11, Steven D'Aprano wrote:
>>> My way
>>> ------
>>>
>>> with func(some_args)<< ':dict':
>>> with when_odd as 'n':
>>> pass
>>> with when_prime as 'n':
>>> pass

>>
>>
>> If you actually try that, you will see that it cannot work. You get:
>>
>> SyntaxError: can't assign to literal

>
> If you had read the module's docstring


What module?


> you would know that the public version uses
> with when_odd << 'n':
> pass


Then why didn't you write that instead of something that gives
SyntaxError? Not once, but EIGHT times.


>> Have you actually tried to use these code blocks of yours? I asked you
>> for a *working* example earlier, and you replied with examples that
>> failed with multiple NameErrors and no hint as to how to fix them. And
>> now you give an example that fails with SyntaxError.

>
> The examples I gave you work perfectly.


Except they don't.

Look, this isn't difficult. I asked for *working* examples, you gave
examples that give NameError. Some of those errors are easy to fix, e.g.
by importing the random and re modules. Some of them aren't. What are
"ris", "repl", "_return", "sorted1", "key"? Where do they come from? What
value should I give them to make your code work?

Code doesn't magically start to work because you declare that it does.
Anyone who takes the time to copy and paste your examples into a fresh
Python interactive session will see that they don't.

Here's one of your earlier examples. I've removed the unnecessary
indentation and made the obvious import, so all it takes to run it is to
copy it and paste into the Python prompt:

import random
numbers = [random.randint(1, 100) for i in range(30)]
with sorted1 << sorted(numbers) << key << 'x':
if x <= 50:
_return(-x)
else:
_return(x)

print(sorted1)


If you try it, you get

NameError: name 'sorted1' is not defined

Fix that (how?) and you'll get another NameError, for 'key', and then a
third, for '_return'.

The syntax isn't very clear. If I had to guess what it does, I'd predict
that maybe it sorts the random list and negates everything <= 50, e.g.
given input [5, 99, 34, 88, 70, 2] it returns [-2, -5, -34, 70, 88, 99].
Obviously that's wrong. You say it should return [34, 5, 2, 70, 88, 99].

The Pythonic way to get that result is:

import random
numbers = [random.randint(1, 100) for i in range(30)]
sorted(numbers, key=lambda x: -x if x <= 50 else x)

which is much more straightforward and obvious than yours, and presumably
much faster. So even if I could get your example working, it would not be
very persuasive.


> It's clear that you don't even
> have the vaguest idea of how my module works or, otherwise, you'd know
> what you're doing wrong.


Well duh. What module? Where do I find it? How am I supposed to know what
this module is when you haven't mentioned it?

Believe it or not, the world does not revolve around you. We cannot see
what is in your head. If we ask for a WORKING EXAMPLE, you need to give
an example that includes EVERYTHING necessary to make it work.

[...]
> Talking with you is a real pain. You're always partial in your opinions
> and this urge of yours to criticize other's work makes you look dumb or
> hopefully just lazy.
> I can't stand people like you who don't even have the decency of taking
> the time to read the documentation of a project and just run their mouth
> without any concern for facts.


What project? You're the one who doesn't tell us what project we're
supposed to use, and yet *I'm* the dumb one.

This is comedy gold.


> What I can't stand is that if I won't reply to your posts other lazy
> people will believe the nonsense you say, but I'll have to live with
> that because I've wasted enough time with you.


Whatever man. It's no skin off my nose. I've tried really hard to give
your proposal a fair go, but my care factor is rapidly running out if you
can't even be bothered to ensure your examples use legal Python syntax.



--
Steven
 
Reply With Quote
 
alex23
Guest
Posts: n/a
 
      05-02-2012
On May 2, 12:18*am, Kiuhnm <kiuhnm03.4t.yahoo.it> wrote:
> "Most Pythonic" doesn't mean better, unfortunately.


Neither does "Kiuhnm prefers it".

> For instance, assume that you want to write a function that accepts a
> dictionary of callbacks:
> * *func(some_args, callbacks)
>
> Pythonic way
> ------------
>
> def when_odd(n):
> * * *pass
>
> def when_prime(n):
> * * *pass
>
> def before_check():
> * * *pass
>
> def after_check():
> * * *pass
>
> func(some_args, {'when_odd' : when_odd,
> * * * * * * * * * 'when_prime' : when_prime,
> * * * * * * * * * 'before_check' : before_check,
> * * * * * * * * * 'after_check' : after_check})


I'm sorry, when would you _ever_ do this? Why are you naming the
functions twice? If you're passing in a dynamic set of functions,
you'd _never know the names_, so my guess is you'd be iterating across
it. If you _do_ know the names, why aren't you accessing them directly
from the surrounding scope? Why aren't you including them in the
function signature?

Presenting bad examples as the Pythonic approach is a bit of a straw
man.

> My way
> ------
>
> with func(some_args) << ':dict':
> * * *with when_odd as 'n':
> * * * * *pass
> * * *with when_prime as 'n':
> * * * * *pass
> * * *with before_check as '':
> * * * * *pass
> * * *with after_check as '':
> * * * * *pass


I'm not sure what value your code blocks really provide.

1. You're effectively making "with when_odd as 'n'" mean "def
when_odd(n)"
2. The 'with code_block_name as arguments' syntax is unintuitive, to
say the least.

Personally, I don't see what value it provides over something more
explicit and standard:

def func(x, before_check=None, after_check=None, when_odd=None,
when_prime=None):
pass

with FOO(func, arg):
def before_check(x):
pass
def after_check(x):
pass
def when_odd(x):
pass
def when_prime(x):
pass

I couldn't think of a name for the context manager...but I can't
really think of a use for it either, so that seems fair.

Actually, here's an even simpler example. In this case, the context
manager doesn't have to interrogate the surrounding stack, but the
function call itself is then explicit.

class FOO(object):
def __init__(self, fn):
self.fn = fn

def __enter__(self):
return self.fn

def __exit__(self, exc_type, exc_value, traceback):
pass

def func(x, before_check=None, after_check=None, when_odd=None,
when_prime=None):
pass

with FOO(func) as f:
def before_check(x):
pass
def after_check(x):
pass
def when_odd(x):
pass
def when_prime(x):
pass

f(1)

But again _what do you gain from this_ other than an extra layer of
unnecessary complexity.
 
Reply With Quote
 
alex23
Guest
Posts: n/a
 
      05-02-2012
[Apologies in advance if this comes through twice]

On May 2, 12:18*am, Kiuhnm <kiuhnm03.4t.yahoo.it> wrote:
> "Most Pythonic" doesn't mean better, unfortunately.


Nor does it mean "Kiuhnm prefers it".

> For instance, assume that you want to write a function that accepts a
> dictionary of callbacks:
> * *func(some_args, callbacks)
>
> Pythonic way
> ------------
>
> def when_odd(n):
> * * *pass
>
> def when_prime(n):
> * * *pass
>
> def before_check():
> * * *pass
>
> def after_check():
> * * *pass
>
> func(some_args, {'when_odd' : when_odd,
> * * * * * * * * * 'when_prime' : when_prime,
> * * * * * * * * * 'before_check' : before_check,
> * * * * * * * * * 'after_check' : after_check})


When would you _ever_ define a function like this? Why are you passing
in _named_ callbacks? Are you calling them by name? Then declare them
in the function signature and rely on scoping. Does func() branch on
existent keys? Then don't write code like that.

At the very _least_, you could change the function call to:

func(some_args, locals())

But as you're _passing them in by name_ why not just make it
func(some_args) and pick them up out of the scope.

_No one_ writes Python code like this. Presenting bad code as
"pythonic" is a bit of a straw man.

> My way
> ------
>
> with func(some_args) << ':dict':
> * * *with when_odd as 'n':
> * * * * *pass
> * * *with when_prime as 'n':
> * * * * *pass
> * * *with before_check as '':
> * * * * *pass
> * * *with after_check as '':
> * * * * *pass


This is unintuitive, to say the least. You're effectively replacing
the common form of function definition with "with when_odd as 'n'",
then using the surrounding context manager to limit the scope.

More importantly, _you're naming your "anonymous" code blocks_, I'm
guessing so that func() can choose which ones to use. But if you're
naming them, why not just use a function?

I'm not entirely sure what your 'solution' offers over something like:

class FOO(object):
def __init__(self, fn):
self.fn = fn

def __enter__(self):
return self.fn

def __exit__(self, exc_type, exc_value, traceback):
pass

def func(x, before_check=None, after_check=None, when_odd=None,
when_prime=None):
pass

with FOO(func) as f:
def before_check(x):
pass
def after_check(x):
pass
def when_odd(x):
pass
def when_prime(x):
pass

f(1)

I called the context manager FOO because I couldn't think of a more
appropriate name (contextscope?)...which is fair, as I can't think of
a use for it either. If you want to automate the function call at the
context manager exit, use something like this instead:

class FOO(object):
def __init__(self, fn, *args, **kwargs):
self.fn = fn
self.args = args
self.kwargs = kwargs

def __enter__(self):
f = inspect.currentframe(1)
self.scope_before = dict(f.f_locals)

def __exit__(self, exc_type, exc_value, traceback):
f = inspect.currentframe(1)
scope_after = dict(f.f_locals)
scope_context = set(scope_after) - set(self.scope_before)
clocals = dict(
[(k, scope_after[k]) for k in scope_context]
)
self.kwargs.update(clocals)
self.fn(*self.args, **self.kwargs)

Maybe there is a compelling use case for code blocks but your toy
example certainly isn't it.
 
Reply With Quote
 
alex23
Guest
Posts: n/a
 
      05-02-2012
On May 2, 12:43*pm, alex23 <wuwe...@gmail.com> wrote:
> I'm not entirely sure what your 'solution' offers over something like:
>
> class FOO(object):
> * * def __init__(self, fn):
> * * * * self.fn = fn
>
> * * def __enter__(self):
> * * * * return self.fn
>
> * * def __exit__(self, exc_type, exc_value, traceback):
> * * * * pass
>
> def func(x, before_check=None, after_check=None, when_odd=None,
> when_prime=None):
> * * pass


Sorry, the func definition was meant to be:

def func(x):
# before_check, after_check, when_odd, when_prime used
internally
pass
 
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
New syntax for blocks r Python 46 11-19-2009 12:32 PM
Methods and blocks - not that clear when blocks passed into Steven Taylor Ruby 9 04-27-2009 08:46 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
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57