Python 4 - New Function Syntax, Maybe?
Tags: python, syntax
Published: 2019-05-01 20:45:25

---
title: Python 4 - New Function Syntax, Maybe?
published: true
description: My thoughts on adding a few new syntaxes for functions to Python 4.0.
tags: python,syntax
---

##Introduction

Hey! I'm xMikee, a small-time developer who writes Python modules for convenience. Recently, I've been studying the Python syntax and comparing it to the syntax of other languages.

I have been using JavaScript a lot recently to work on my web-based projects. I switch back and forth between which language I use (obviously for different use cases), and it really helps me understand the differences between the two languages. Some notable ones:

* Braces - Python relies heavily on indentation

* `super` (no function calling in JS but a function in Python)

* `this` (refers to the object something belongs to in JS)

* `get`/`set` (special syntax in JS but decorators in Python)

* Spread syntax (basically the equivalent of `*variable` in Python)

* Dictionaries (no quotes required for keys in JS, the opposite for Python)

And probably many more I am forgetting. Now obviously, these languages do not share the same principles and therefore the syntax will be very different (JS is C-style, but Python is not). But I'd like to add some aspects of JavaScript into Python. *Whaaaaaat?* Don't freak out too much, I'll explain.

* * *

Let me just start my saying that there is absolutely nothing wrong with Python functions the way they are now. I'm not trying to go out there and propose that we add braces to the language in any way. It would be perfectly fine if this proposal was rejected. I'd like to try and tackle readability issues with functions as parameters. Don't quite get what I'm saying? Here's an example.

Let's say that you are using the Fetch API in JavaScript to do a web request. Here's what your sample code may look like:

```javascript
fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(JSON.stringify(myJson));
  });
```

Now, let's translate this program to pseudo-Python (obviously `fetch` is not a Python function, but we're just translating):

```python
import json

def handler1(response):
  return response.json()

def handler2(myJson):
  print(json.dumps(myJson))

fetch('http://example.com/movies.json')
  .then(handler1)
  .then(handler2)
```

Not quite as pretty, is it? Let's point out the differences here.

* In JavaScript, we could define our functions inline. This increased readability since we can see the clear connection in what functions are being processed and how it fits into the flow of the program.

* In Python, we had to define separate functions for both of the handlers. Since Python does not directly support inline functions (excepting lambda expressions - we'll cover that later), we had to define separate functions to pass in as the handlers. In a much more complex program, this could quickly get out of hand and be unclear what functions are being executed where.

This seems to be against a few of of Python's core values, defined in [the Zen of Python](https://www.python.org/dev/peps/pep-0020/#the-zen-of-python):

> Simple is better than complex.
> ...
> Readability counts.

Interesting, right? Now, let's come back to lambda expressions. Lambdas are callable expressions in Python - **not** functions. Lambdas are good for passing in one-expression methods (for instance, our example above probably could have been converted to two lambdas). But that's pretty much all they're good for.

Once you start requiring more than one expression in your functions, or statements, you'll need to switch over to functions. This is because lambdas are *expressions*, and therefore only accept expression syntax, not statements. The fact that you can only use one complete expression severely limits the capabilities of lambda expressions in larger-scale programming with more complex operations.

Therefore, we need to use functions in most cases. As we saw above, it's ugly to define them separately just so they can be used as a parameter. There's really no solution to this issue - at least, not yet.

* * *

## My Proposal

<small>*I apologize in advance. The syntax highlighting does display some dark red/black text because the proposed features are technically invalid syntax. Try to ignore the apparent syntax errors.*</small>

Due to strict indentation requirements in Python, it would be very difficult to implement a true system of inline functions while still being somewhat attractive and practical. I believe I have found a happy medium between all these options to create an attractive, useful syntax. Here's the example from above, except using the new syntax:

```python
import json

fetch('http://example.com/movies.json')
  .then((def (response):
    return response.json()
  ))
  .then((def (myJson):
    print(json.dumps(myJson))
  ))
```

Let's pull apart these lines.

```python
.then((def (response):
  return response.json()
))
```
* The entire function is parenthesized. This is required if passing it directly as a function to allow for other arguments to be passed along side the inline function.

* The `def` statement has no name following it - the arguments start immediately.

* Indentation is still required and mandatory (and actually fits quite nicely in  the arguments, if I must say so myself).

* An ending parenthesis ends the inline function. More arguments can be added at this point to the function.

Not too shabby, right? This is what my proposal is. It's called Inline Function Syntax. Distinct from lambda expressions, inline functions are completely capable of performing any tasks a regular function may require.

Here's another example for your viewing. It uses the `map` function. Previously, in order to write more complex operations, you would have to use a whole separate function instead of a lambda, which is unwieldy. But now, here's the function *inlinified*:

```python
result = map(range(60), (def (number):
  if number % 2 == 0:
    return "even"
  elif number % 2 == 1:
    return "odd"
  else:
    return "whoa, freaky number"
))
```

You see? It even looks somewhat attractive! We were able to pass in `range(60)` as our first parameter, and we could even pass in more arguments after the function if we wanted to, like this:

```python
result = map(range(60), (def (number):
  if number % 2 == 0:
    return "even"
  elif number % 2 == 1:
    return "odd"
  else:
    return "whoa, freaky number"
), another_value)
```

Of course, inline functions are objects. That means they can be assigned to variables. Here's another example using an inline function, but this time assigning it to a variable:

```python
freaky = def (number):
  if number % 2 == 0:
    return "even"
  elif number % 2 == 1:
    return "odd"
  else:
    return "whoa, freaky number"

result = map(range(60), freaky)
```

So that's just basically an alternate syntax for function creation. Since inline functions are really just functions in a nutshell, it's not really surprising that they support [type hinting/function annotations](https://stackoverflow.com/a/32558710/):

```python
from typing import Iterator

fib = def (n: int) -> Iterator[int]:
  a, b = 0, 1
  while a < n:
    yield a
    a, b = b, a+b

result = fib(60)
```

Type hints are also supported when passing an inline function as a function parameter due to the fact that indentation is preserved. 

There's one more special *gotcha*, and this is inspired directly from JavaScript (even more than the rest of the syntaxes in this post). It's called Immediately Invoked Function Expressions. That's a direct JavaScript feature ([read about in on MDN](https://developer.mozilla.org/en-US/docs/Glossary/IIFE). You can use it to produce privately scoped variables to perform a calculation. without storing the function afterwards.

Here's an example. Say we want to generate the first 60 Fibonacci numbers, but we want all the variables to be private and we don't want the function stored afterwards. Here's an example:

```python
result = (def (n):
  a, b = 0, 1
  while a < n:
    yield a
    a, b = b, a+b
)(60)
```

It's important to note that the function **must** be parenthesized, so that the function and the call can be separated. This can be useful in some instances.

* * *

If we're speaking honestly here, I don't think this would *ever* be implemented, not even a little bit. But it's just another thing I'm proposing to spice up the language. :)

Of course, this would also come with it's own host of incompatibility issues as well. But that's what you get with any interesting syntax change.

Let's hear your thoughts down below. What do you think about functions? Would the Python community benefit from a change like this, or would it hurt the language? Thanks for reading, and here's [a cat](https://images.unsplash.com/photo-1547565393-1b180d53d82a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80) because you read all the way to the end. 😺