Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Postpone evaluation of argument (http://www.velocityreviews.com/forums/t868174-postpone-evaluation-of-argument.html)

Righard van Roy 02-10-2012 11:01 PM

Postpone evaluation of argument
 
Hello,

I want to add an item to a list, except if the evaluation of that item
results in an exception.
I could do that like this:

def r(x):
if x > 3:
raise(ValueError)

try:
list.append(r(1))
except:
pass
try:
list.append(r(5))
except:
pass

This looks rather clumbsy though, and it does not work with i.e. list
comprehensions.

I was thinking of writing a decorator like this:

def tryAppendDecorator(fn):
def new(*args):
try:
fn(*args)
except:
pass
return new

@tryAppendDecorator
def tryAppend(list, item):
list.append(item)

tryAppend(list, r(1))
tryAppend(list, r(5))

This does not work however because the 'item' argument gets evaluated
before the decorator does it's magic.

Is there a way to postpone the evaluation of 'item' till it gets used
inside the decorator. Like it is possible to quote a form in Lisp.

Thank you,
Righard

Paul Rubin 02-10-2012 11:57 PM

Re: Postpone evaluation of argument
 
Righard van Roy <pluijzer@gmail.com> writes:
> I want to add an item to a list, except if the evaluation of that item
> results in an exception.


This may be overkill and probably slow, but perhaps most in the spirit
that you're asking.

from itertools import chain

def r(x):
if x > 3:
raise(ValueError)
return x

def maybe(func):
try:
yield func()
except:
return

def p(i): return maybe(lambda: r(i))

your_list = list(chain(p(1), p(5)))
print your_list

Jussi Piitulainen 02-11-2012 08:54 AM

Re: Postpone evaluation of argument
 
Righard van Roy writes:

> Hello,
>
> I want to add an item to a list, except if the evaluation of that item
> results in an exception.
> I could do that like this:
>
> def r(x):
> if x > 3:
> raise(ValueError)
>
> try:
> list.append(r(1))
> except:
> pass
> try:
> list.append(r(5))
> except:
> pass
>
> This looks rather clumbsy though, and it does not work with i.e. list
> comprehensions.
>
> I was thinking of writing a decorator like this:
>
> def tryAppendDecorator(fn):
> def new(*args):
> try:
> fn(*args)
> except:
> pass
> return new
>
> @tryAppendDecorator
> def tryAppend(list, item):
> list.append(item)
>
> tryAppend(list, r(1))
> tryAppend(list, r(5))
>
> This does not work however because the 'item' argument gets evaluated
> before the decorator does it's magic.
>
> Is there a way to postpone the evaluation of 'item' till it gets used
> inside the decorator. Like it is possible to quote a form in Lisp.


That's not considered good practice in Lisp either. One would use a
lambda expression to delay the computation, as others have suggested.

You might be able to arrange your program so that tryAppend is called
with the error-raising function and its arguments separately. I mean
like this:

def r(x):
if x > 3:
raise(ValueError)
return x

def tryAppendDecorator(fn):
def new(xs, f, *args):
try:
fn(xs, f(*args))
except:
pass
return new

@tryAppendDecorator
def tryAppend(items, item):
items.append(item)

sub3 = []
tryAppend(sub3, r, 3)
tryAppend(sub3, r, 1)
tryAppend(sub3, r, 4)
tryAppend(sub3, r, 1)
tryAppend(sub3, r, 5)

Maybe you should only ignore some specific type of exception, like
ValueError if you are specifically using r as a filter whose task it
is to raise a ValueError.

88888 Dihedral 02-11-2012 11:16 AM

Re: Postpone evaluation of argument
 
在 2012年2月11日星期*UTC+8上午7时57分56秒 ,Paul Rubin写道:
> Righard van Roy
> writes:
> > I want to add an item to a list, except if the evaluation of that item
> > results in an exception.

>
> This may be overkill and probably slow, but perhaps most in the spirit
> that you're asking.
>
> from itertools import chain
>
> def r(x):
> if x > 3:
> raise(ValueError)
> return x
>
> def maybe(func):
> try:
> yield func()
> except:
> return
>

I am wondering at which level to yield in a nested decorated function
is more controllable.

It is definitely wrong to yield in manny levels decorated.


> def p(i): return maybe(lambda: r(i))
>
> your_list = list(chain(p(1), p(5)))
> print your_list




All times are GMT. The time now is 11:35 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.