Postpone evaluation of argument

R

Righard van Roy

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
 
P

Paul Rubin

Righard van Roy said:
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
 
J

Jussi Piitulainen

Righard said:
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.
 
8

88888 Dihedral

在 2012å¹´2月11日星期六UTC+8上åˆ7æ—¶57分56秒,Paul Rubin写é“:
Righard van Roy
writes:

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top