Some of Python's language constructs, like variable binding, exception
handling, sequencing, and iteration, are provided only through
language statements. You cannot use statements in an expression
context, so it would seem we are up against a limitation. But Python
has lambda
expressions. Lambda expressions and function
calls are all you need to implement variable binding, sequencing and
recursion as ordinary Python expressions.
For example, suppose you wish to have a 'let
' expression
where you bind helper variables 'a
' and 'b
'
to subexpressions. Simply use lambda
and immediately call it:
return (lambda a, b: h(a, b))(f(x), g(y))Not pretty, but it gets the job done. If you want to sequence two expressions, write them like this:
return (lambda ignore: x + 7)(print (x))The
print
expression runs first, its result is ignored and then x
is
added to 7 and returned. Again, this could use a lot of syntactic
sugar, but it gets the job done. Alternatively, we could use left to
right evaluation of arguments to do our sequencing:return (lambda first, second: second)(print(x), x + 7)In order to implement iteration, we need to bind a name recursively. We'll use the Y operator.
Y = lambda f: (lambda d: d(d)) (lambda x: f (lambda: x (x))) print (Y (lambda loop: \ lambda x: \ None if x == 0 else (lambda first, second: second)( print (x), loop()(x - 1))) (5)) 5 4 3 2 1 0 None
Handling exceptions is easy if you use a helper function and some thunks:
def on_error (compute_value, handle_error): try: return compute_value() except: return handle_error() def safe_divide (dividend, divisor): return on_error ( lambda: dividend / divisor, lambda: (lambda first, second: second)( print ('divide by zero, answer 1'), 1)) print (safe_divide (12, 3)) 4 print (safe_divide (12, 0)) divide by zero, answer 1 1
No comments:
Post a Comment