Every programmer knows that large problems can be split into smaller subproblems. It is done by combining the code for a subproblem in a procedure or function (or a method if we want to create a class). This has several advantages:
- It defines a clear boundary for the code which solves the subproblem
- It clearly defines the inputs (parameters) and the outputs (return value) of the code
- It allows to use the same code at several places in the code
Let’s discuss the problem with a typical example:
def main_function(param):
#…
#(do some stuff to create an intermediate result from param)
#…
intermediate_result = a * b # some stuff
#…
#(do some stuff with intermediate_result)
#…
return result
The code in the first part of the function is used to calculate the value of intermediate_result. Nothing else is needed anymore as soon as this code has been executed. We also assume that the intermediate_result is something clearly defined and easy to understand. Then, most programmers would probably suggest to rewrite the code as follows for clarity:
def calculate_intermediate_result(param)
#…
#(do some stuff to create the intermediate result from param)
#…
return intermediate_result
def main_function(param):
intermediate_result = calculate_intermediate_result(param)
#…
#(do some stuff with intermediate_result to calculate result)
#…
return result
But there is a small problem with this: the creation of the new function calculate_intermediate_result means that the code which it contains can be reused. This means that whenever we want to change some code within calculate_intermediate_result this is not a matter of main_function only anymore. We have to check for other parts of the code which use this function too and make sure that the modified function works with those flawlessly too. Even if calculate_intermediate_result is defined only in the local context (i.e. defined within main_function) we still have to be careful now as it could be called from several locations in main_function.
This makes the code a bit harder to read, even if we don’t intend (now) to reuse the function somewhere else. If we do this all the time, the difference can be noticeable.
Therefore the temptation to avoid creating a new function is always there. I sometimes create structures like this:
def main_function(param):
# 1. Now we calculate intermediate_result
#(do some stuff to create an intermediate result from param)
intermediate_result = a * b # some stuff
# 2. Now we calculate the result from intermediate_result
#(do some stuff with intermediate_result)
#…
return result
But this pattern has also severe disadvantages:
- Comments are now carrying important semantic information (how the code is actually structured, what is input and output etc.). This is bad as this information should be contained in the code itself (the reasons for this are well known and I will not bore you with repeating them here)
- The namespace in the 2nd part is polluted with all the names from above (but only one of them is really still required). This is particularly problematic in dynamically typed languages like python.
To solve this dilemma, I suggest to add the following feature to the language (easiest to explain with our example):
def main_function(param):
# …
#(do some stuff to create an intermediate result)
intermediate_result = a * b # some stuff
sec calculate_result(intermediate_result): # <-- THE MAGIC HAPPENS HERE!
#(do some stuff with intermediate_result)
#…
return result
sec (for section) would be syntactically identical to a def and would do the following:
- clear the namespace from all the variables defined above and keep only intermediate_result
- Give an in-language explanation what the following code block is expected to do (calculate the result in the example) and what is really required from the previous code block (the parameter intermediate_result in the example)
Basically the definition of a section would allow us to group commands in exactly the same way a function does, but without allowing reuse yet: If we later decide that we would like to reuse the code somewhere else, the section-code can be converted into a proper function trivially (i.e. without thinking).
What do you think?
Image: Shutterstock, Kurit afshen