# Guido was right, there should be no lambda in Python.

04^{th}March 2018

Python has support for lambda functions, Haskell is built upon lambda calculus. The two are not the same and this is the reason why lambda should have been removed in Python3. This post examines the differences, reviews the use in Python, and offers a more pythonic, honest syntax.

LAMBDA IN Python has been derived from functional programming, however
there is nothing that lambda can do that can’t be done with the usual
`def foo(*args, **kwargs): ...`

syntax. At the advent of Python3 Guido proposed
to remove lambda from Python,
but relented and allowed it to stay.

Haskell is a canonical functional programming language, it relies heavily on
lambda calculus, although it does have a lambda syntax : `(\x -> x + 1)`

, this is equivalent to `(+1)`

. How can this be? Every function is a lambda function.

We’ll take a quick look at lambda calculus using Python. Then I’ll claim **we
don’t use lambda calculus in Python**, despite
all the great advantages it gives Haskell programmers. Finally we’ll look at how we
use `lambda`

in Python and discuss why it should have been changed going into Python3.

I know this will be an aggravating read for many
pythonistas, but please try to remain calm and keep an open mind. **Don’t
comment without reading first!**

## Lambda Calculus

LAMBDA CALCULUS (aka. \lambda-calculus)
is Turing Complete, meaning **we can make programs from just lambda**. In lambda calculus, the
function `lambda x: x`

would be written as \lambda x.x.

In Python we have some syntactic sugar, `lambda x, y: x + y`

is actually accepting a tuple
of arguments. In the examples I’m being strict and passing arguments individually as per the
maths syntax \lambda x. \lambda y. x + y.

To resolve a lambda expression, we substitute in arguments. I’ve shown it in Python syntax so you can run the functions.

(lambda x: (lambda y: x + y))(2)(3) (lambda y: 2 + y)(3) 2 + 3

You can use this syntax to create all manner of programs because **you can substitute
functions as well as values**.

Here we have a function that accepts another function and a single argument. It is given a function that adds 1 to a single argument, and then it is given 4 as an argument.

(lambda f: (lambda a: f(a)))(lambda x: x + 1)(4) (lambda a: (lambda x: x + 1)(a))(4) (lambda a: a + 1)(4) 4 + 1

As a glimpse into what can be done with lambda calculus, here’s an ‘if-then-else’ branching function where we’ve broken the rules of lambda calculus by naming the functions to aid readability.

For more about lambda calculus in Python syntax, I’d recommend a talk from EuroPython 2017 by Anjana Vakil, called “Mary had a little lambda”.

TRUE = lambda x: lambda y: x FALSE = lambda x: lambda y: y IFELSE = lambda p: lambda a: lambda b: p(a)(b) print(IFELSE(TRUE)(1)(2)) # Output: 1 print(IFELSE(FALSE)(1)(2)) # Output: 2

## Lambda Calculus: **+**

LAMBDA, WHEN used in a programming language to define functions gives you currying and thus partial application built in. If you’ve read Python Partial: Code Your Intention, you’ll know I’m a big fan of this.

Lambda calculus can provide features we find in Python, which we know and love, such as first-class functions and higher-order functions, because we can pass functions around.

It can also be used for lazy evaluation: the substitutions can be undertaken without executing the functions. This also allows a compiler, such as the Haskell compiler, to reduce the computation required when composing functions together.

**No** Lambda in Python

I LOVE the benefits of lambda calculus, I love Python. The two do not mix. In Python our functions are not curried or evaluated using lambda calculus, we know this because functions need all their arguments when called. Consider the difference between these two addition functions.

`l_add`

needs the arguments passed one at a time. We never see this syntax with multiple parenthesis
in Python. It works and it has many benefits built in, but it would be a paradigm
shift to expect pythonistas to start writing their programs this way, it’s just
not Pythonic.

def add(a, b): return a + b l_add = lambda a: lambda b : a + b add(1, 2) l_add(1)(2)

Compare this to Haskell, which is built for using lambda calculus. Haskell’s syntax is less verbose, easier to write, there’s no annoying parenthesis and the benefits of currying are built in.

-- declaring the function l_add a b = a + b -- calling the function l_add 1 2 -- partial application incr = l_add 1 -- calling the partial function incr 2

**But That’s Not How We Use Lambda In Python**

I KNOW! In Python we call our functions with all their arguments at the same time, even `lambda x, y: x + y`

is expecting both arguments together. Typical use cases in Python are for very short inline functions, usually when being passed to a higher-order function.

During the debate about removing lambda from Python3,
Kay Schluehr proposed an inline syntax,
it should be possible to make use of the use of `_`

with `inline`

to create anonymous
functions that fulfil our requirement, encode our intention, and stay pythonic.

In Python ** lambda is a short,
inline, anonymous function**. But,

**an anonymous function is not a calculus.**

# Typical use cases map(lambda x: x + 1, range(5)) max(my_tuples, key=lambda t: t[1]) # More pythonic? Closer to the user intent? map(inline _(x): x + 1, range(5)) max(my_tuples, key=inline _(t): t[1])

## Add Sugar

**PYTHON IS capable
of lambda calculus, but it is not considered pythonic to use it.** If a
library like `datetime`

were to use lambda calculus there would be outcry from the community,
no-one would want to call functions with a set of parenthesis for each argument.

But the **normal way to call a function could be made syntactic sugar for
the lambda calculus way**. Just like in Haskell, Python would not *need*
a `lambda`

syntax. This imaginary case reveals how the `lambda`

syntax is not being
used appropriately. If `def foo(x): ...`

were this syntactic sugar, how would we declare our inline anonymous functions?

# Normal python call: datetime.date(2018, 3, 4) # Lambda calculus call: datetime.date(2018)(3)(4)

If you like that syntactic sugar, check out toolz curry. Wouldn’t it be nice if we didn’t have to use the decorator?

## Conclusion

IF EVERY function were a lambda function with some syntactic sugar, we’d still
need a way to declare inline anonymous functions. This brings us back to needing
something like `inline _(): ...`

. This also brings back my argument for all
the functional programming techniques I have covered in this blog so far: **Code
the authors intention**.

In Python, **we do not use lambda with the intention of using lambda calculus**. Our
syntax needs to encode our intention in the places we have used it, and where we will use it.
These use cases are inline, anonymous functions.

Love it? Hate it? What do you think? Let me know in the comments and happy coding.Paul

## Comments

JOIN THE conversation: awesome comments.