| 
        
       | 
      
        func simple() {
    print("hi")
}
simple()                                // hi
 
       | 
    
    
      | 
         Parameter types and the return type must be specified.
       | 
      
        func plus(a: Int, b: Int) ->Int {
    return a + b
}
func sum(numbers: [Double]) -> Double {
    var sum: Double = 0.0
    for num in numbers {
        sum += num
    }
    return sum
}
 
       | 
    
    
      | 
         Functions can return tuples.
       | 
      
        func stats(numbers: [Int]) -> (min: Int, max: Int) {
    var min = Int.max, max = Int.min
    for i in numbers {
        if i < min {
            min = i
        }
        if i > max {
            max = i
        }
    }
    return (min, max)
}
 
       | 
    
    
      | 
         Functions that don't return anything return
       | 
      
          
       | 
    
    
      
         Void (an empty tuple) by default.
       | 
      
        func noop(){}
noop()
var result = stats([1, 2, 4])
print(result.min)                      // 1
print(result.max)                      // 4
 
       | 
    
    
      | 
         Named parameters use an 'external' name before the 'internal' name.
       | 
      
          
       | 
    
    
      | 
         Kind of a kludgy holdover from Obj-C selectors...
       | 
      
        func increment(number: Int, by incrementer: Int) -> Int {
    return number + incrementer
}
print(increment(1, by: 10))           // 11
 
       | 
    
    
      | 
         ...So fortunately there's a shorthand for re-using the same name.
       | 
      
        func incrementTakeTwo(number: Int, by: Int) -> Int {
    return number + by
}
print(increment(1, by: 10))           // 11
 
       | 
    
    
      | 
         Parameter values aren't modifiable by default.
       | 
      
          
       | 
    
    
      | 
         But you can declare that you want to change a parameter
       | 
      
          
       | 
    
    
      | 
         value (within the function) with a var keyword.
       | 
      
        func addOne(var num: Int) -> Int {
    num++
    return num
}
addOne(1)                             // 2
 
       | 
    
    
      
         # Default parameter values
       | 
      
          
       | 
    
    
      | 
         Swift realizes that the verbosity is becoming a burden.
       | 
      
          
       | 
    
    
      | 
         So default params' internal names are also auto-exposed
       | 
      
          
       | 
    
    
      | 
         with the same external name.
       | 
      
        func incrementTakeThree(number: Int, by: Int = 3) -> Int {
    return number + by
}
print(incrementTakeThree(1))         // 4
print(incrementTakeThree(1, by:1))   // 2
 
       | 
    
    
      
         # Variadic parameters
       | 
      
          
       | 
    
    
      | 
         (Aside: functions can be overloaded since they're different types [more below])
       | 
      
        func sum(nums: Double...) -> Double {
    var sum: Double = 0.0
    for num in nums {
        sum += num
    }
    return sum
}
 
       | 
    
    
      | 
         Unfortunately, splats aren't supported
       | 
      
          
       | 
    
    
      | 
         
       | 
      
          
       | 
    
    
      | 
         So you can't call a variadic function with an array of args.
       | 
      
        func average(nums: Double...) -> Double {
    return sum(nums) / Double(nums.count)
}
average(1.0, 2.0, 3.0, 4.0)            // 2.5
 
       | 
    
    
      
         # In-Out (pass-by-reference) parameters
       | 
      
          
       | 
    
    
      | 
         inout params cannot be declared as var or let.
       | 
      
        func addOneSideEffect(inout num: Int) {
    num++
}
 
       | 
    
    
      | 
         Cannot pass constants and literals.
       | 
      
        var num = 1
 
       | 
    
    
      | 
         Use an & before the var's name.
       | 
      
        addOneSideEffect(&num)
print(num)                         // 2
 
       | 
    
    
      
         # Function Types
       | 
      
          
       | 
    
    
      | 
         Assign functions to variables.
       | 
      
          
       | 
    
    
      | 
         The function type (signature) of the function
       | 
      
          
       | 
    
    
      | 
         must be repeated.
       | 
      
        var mean: (Double...) -> Double = average
mean(1.0, 4.0)                      // 2.5
 
       | 
    
    
      | 
         The variable can be re-assigned to another function as
       | 
      
          
       | 
    
    
      | 
         long as that function has the same type.
       | 
      
          
       | 
    
    
      | 
         Function types can be used as parameters.
       | 
      
        func skewedMean(mean: (Double...) -> Double, num1: Double, num2: Double) -> Double {
    return mean(num1, num2) + 1.0
}
skewedMean(mean, num1: 1.0, num2: 4.0)          // 3.5
 
       | 
    
    
      | 
         Function types can be returned from functions.
       | 
      
        func choose(which: String) -> (Double...) -> Double {
    if which == "sum" {
        return sum
    }
    return mean
}
choose("sum")(1.0, 2.0)            // 3.0
choose("mean")(1.0, 2.0)           // 1.5
 
       | 
    
    
      
         # Nested Functions
       | 
      
          
       | 
    
    
      | 
         Nested functions cannot be referenced outside of their parent function.
       | 
      
        
func summer(var num: Double) -> (Double...) -> Double {
    // Closure: the nested function is able to close over `num`.
    func internalFunc (numbers: Double...) -> Double {
        for i in numbers {
            num += i
        }
        return num
    }
    return internalFunc
}
summer(1.0)(2.0, 3.0)              // 6.0
 
       |