Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Postpone evaluation of argument

22 views
Skip to first unread message

Righard van Roy

unread,
Feb 10, 2012, 6:01:52 PM2/10/12
to pytho...@python.org
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

Chris Rebert

unread,
Feb 10, 2012, 6:12:38 PM2/10/12
to Righard van Roy, pytho...@python.org
Nope. All arguments always get evaluated before control passes to the
callee. You'd have to "quote" the arguments manually by putting them
in lambdas, thus explicitly delaying their evaluation.

Cheers,
Chris
--
http://rebertia.com

Paul Rubin

unread,
Feb 10, 2012, 6:57:56 PM2/10/12
to
Righard van Roy <plui...@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

unread,
Feb 11, 2012, 3:54:10 AM2/11/12
to
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

unread,
Feb 11, 2012, 6:16:39 AM2/11/12
to
在 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.
0 new messages