print("Happy birthday to you.")
print("Happy birthday to you.")
print("Happy birthday, dear Chris.")
print("Happy birthday to you.")

"""
Explanation: Functions
Functions in Python work straight-forward: They (optionally) require a set of inputs, perform some internal operations, and return a result. Now, we could either go on talking about the basic syntax of function declaration, how the whole story works, etc... OR we could simply take a look at the following image that puts it all in a graphical, and hence, easy-to-understand context (all the credit is due to <a href="http://learnict.it/computerscienceposters/">LearnICT.it</a>):
<br>
<center>

<figure>
    <img src="http://hcc-cs.weebly.com/uploads/2/4/5/3/24535251/1088210.jpg?1390056443" alt="functions" width="690">  
    <figcaption>Source: http://hcc-cs.weebly.com/functions.html</figcaption>
  </figure>
</center>
<br>
Okay, so just for the record, here's the syntax of function definitions in Python:

def function_name () : <br>
&ensp;&ensp;&ensp;indentedFunctionBody

So, what's the purpose of functions anyway? Well... suppose we wanted to write some Python code that reproduces the lines of the famous "Happy Birthday" song (taken from <a href="http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/functions.html">here</a>). In order to achieve this and assuming our birthday child's name is Chris, we could simply use some print calls:
End of explanation
"""


print("Happy birthday to you.")
print("Happy birthday to you.")
print("Happy birthday, dear Thomas.")
print("Happy birthday to you.")

"""
Explanation: But what if we wanted to reuse this code to congratulate someone else, e.g. named Thomas? There's basically two (fundamentally different) approaches here: We could either copy and paste the above code, replacing the name of the birthday child:
End of explanation
"""


def birthdaySong(name):
    print("Happy birthday to you.")
    print("Happy birthday to you.")
    print("Happy birthday, dear ", name, ".", sep = "")
    print("Happy birthday to you.")
    
birthdaySong(name = "Thomas")    

"""
Explanation: Or &ndash; and here's where the high art of programming actually begins &ndash; write a function that takes a certain input variable (i.e. the name), performs some processing steps (i.e. put the single lines together), and returns the result (i.e. the complete song).
End of explanation
"""


def birthdaySong(name = "Chris"):
    for i in range(4):
        if (i != 2):
            print("Happy birthday to you.")
        else:
            print("Happy birthday, dear ", name, ".", sep = "")
            
birthdaySong()            

"""
Explanation: Using our newly gained knowledge about <a href="https://oer.uni-marburg.de/goto.php?target=pg_5101_720&client_id=mriliasmooc">E02-1: Loops</a> and <a href="https://oer.uni-marburg.de/goto.php?target=pg_5102_720&client_id=mriliasmooc">E02-2: Conditionals</a> from before, we could take this even a step further and restructure the function's body using a for loop together with embedded if-else statements:
End of explanation
"""


def f1():
    return()

f1()

"""
Explanation: Please note that in the latter version, we also set a default value for name in order to save some typing work on Chris's birthday. In the end, it is totally up to you which of the two versions you prefer, i.e. four print statements in a row or rather the nested for/if-else solution. 
<hr>

The return statement
So far, you have only encountered selfmade functions that print some text to the console. However, the majority of functions you'll be writing in the future need to perform actual calculations based on a set of input variables and then return an output object. 
Therefore, in addition to the things we have just learned, bear in mind to insert a return statement whenever you are actually trying to return an object. For example,
End of explanation
"""


def f2():
    return(5)

f2()

"""
Explanation: returns an empty tuple, whereas
End of explanation
"""


def sumPy(x):
    out = 0.0
    
    for i in x:
        out += i
        
    return(out)

sumPy(range(0, 6))

"""
Explanation: returns an int object. Accordingly, a custom sum function that takes a sequence of numbers as input could roughly look as follows:
End of explanation
"""


