Postpone evaluation of argument

Jussi Piitulainen jpiitula at ling.helsinki.fi
Sat Feb 11 03:54:10 EST 2012


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.



More information about the Python-list mailing list