Beginner's Guide

# Functions (Basics)Functions (Basics)Functions

## BasicsBasics

###### Example: Function that computes mean of 2 numbers
``````double mean (double a, double b) {
return (a + b) / 2;
}
int main() {
cout << mean(2, 6);  // prints 4
}``````
• encapsulation of implementation details
• easier reasoning about correctness and testing by breaking down problems into separate functions
• avoids repeating code for common tasks ``````// "call" at "call site"
auto result = name(argument1, argument2);``````

## Return Types

###### Full Return Type Deduction   (deduction = compiler determines type automatically)
``````auto foo (int i, double d) {
…
return i;
}
//  deduced return type: int``````
``````auto foo (int i, double d) {
return i;  //  int
…
return d;  //  double
}
//  COMPILER ERROR: Inconsistent return types!``````

## Parameters

• none: `f()`
• one or many: `g(int a, double b, int c, …)`
• parameter names have to be unique within list

#### `const` Parameters`const`

``````int foo(int a, int const b) {
a += 5;   //
b += 10;  //  COMPILER ERROR: can't modify const parameter
return (a + b);
}
// calling foo:
foo(2,9);  // const has no effect here``````

Any 2nd argument passed to `foo` will be copied testi into the local variable `b` ⇒ the fact that `b` is `const` has no effect outside of `foo`.

If you don't need or must not change values of parameters then make them `const`!

#### Defaulted ParametersDefaults

``````double f (double a, double b = 1.5) {
return (a * b);
}
int main() {
cout <<  f(2);     // 1 argument  → 3.0
cout <<  f(2, 3);  // 2 arguments → 6.0
}``````
``````void foo (int i = 0);
void foo (int n, double x = 2.5);
void foo (int a, int b = 1, float c = 3.5f);
void foo (int a, int b = 1, int c );  ``````
Each parameter after first default must have default value, too!

• functions with the same name but different parameter lists
• cannot overload on return type alone

## Recursion

###### = function calling itself
• needs a break condition
• looks more elegant than loops but in many cases slower
• recursion depth is limited (by stack size)
``````int factorial (int n) {
// break condition:
if(n < 2) return 1;
// recursive call: n! = n * (n-1)!
return (n * factorial(n - 1));
}``````

## Declaration vs. DefinitionDeclaration

• can only call functions that are already known (from before/above)
• only one definition allowed per source file (translation unit)
• ok to have any number of declarations = announcing the existence of a function by specifying it's signature
##### Example: Broken! (click!)
`````` COMPILER ERROR: - 'odd'/'even' not known before 'main'!
COMPILER ERROR: - 'odd' not known before 'even'!
int main() {
int i = 0;
cin >> i;
if(odd(i))  cout << " is odd\n";
if(even(i)) cout << " is even\n";
}
bool even(int n) {
return !odd(n);
}
bool odd(int n) {
return (n % 2);
}``````
##### Working (click!)
``````bool even(int);  // declaration
bool odd(int);   // declaration
int main() {       // definition
int i = 0;
cin >> i;
if(odd(i))  cout << " is odd\n";   // OK, already declared
if(even(i)) cout << " is even\n";  // OK, already declared
}
bool even(int n) {   // definition
return !odd(n);  // OK, already declared
}
bool odd(int n) {    // definition
return (n % 2);
}``````

## Design

###### When implementing a function, think about:
• Preconditions: What do you expect/demand from input values?
• Postconditions: What guarantees should you give regarding output values?
• Invariants: What do callers/users of your function expect to not change?
• Purpose: Has your function a clearly defined purpose?
• Name: Does the function's name reflect its purpose?
• Parameters: Can a caller/user easily confuse their meaning? Users of a function should not be confused about its purpose, the meaning of its parameters, pre/postconditions and side effects.

Interfaces should be easy to use correctly and hard to use incorrectly.  —  Scott Meyers

## Some Mathematical FunctionsMathematical FunctionsMath

 `#include ` `double sqrt (double x)` √x square root `double pow (double a, double b)` ab power `double abs (double x)` |x| absolute value `double sin (double x)` sin(x) sine `double cos (double x)` cos(x) cosine `double exp (double x)` ex exponential `double log (double x)` log(x) logarithm `double floor (double x)` ⌊x⌋ next smaller integer `double ceil (double x)` ⌈x⌉ next larger integer `double fmod (double x, double y)` remainder of x/y