
Defining and Calling Functions #
1. Core Concepts #
- Concept Explanation: A function is a self-contained chunk of code that performs a specific task. Every function has a type, consisting of its parameter types and return type.
- Key Syntax:
func,->,return
2. Example #
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
print(greet(person: "Anna"))
// Prints "Hello, Anna!"Logic Explanation:
This code defines a function named greet. It accepts a parameter person of type String and returns a String. The -> symbol is used to indicate the return type. When calling it, you must write the argument label person: "Anna".
3. C# #
Concept Mapping: This is equivalent to a Method definition in C#.
C# Example:
public string Greet(string person) {
string greeting = "Hello, " + person + "!";
return greeting;
}
// Call
Console.WriteLine(Greet("Anna")); // Argument name not mandatory
// Or using named arguments
Console.WriteLine(Greet(person: "Anna"));Key Differences Analysis:
- Syntax: Swift uses the
funckeyword, and the return type is written after the arrow->; C# places the return type before the method name. - Behavior: The most significant difference lies in calling conventions. Swift defaults to requiring Argument Labels at the call site, making the code read like a sentence; while C# supports Named Arguments, they are less commonly enforced by convention.
Function Parameters and Return Values #
1. Core Concepts #
- Concept Explanation: Swift’s parameters and return values are very flexible. It supports no parameters, multiple parameters, no return value (effectively returning
Void), and multiple return values via Tuples. - Key Syntax:
Void,Tuple,Optional Tuple - Note:
Strictly speaking, functions without a defined return type still return a value. They return a special value of type
Void, which is actually an empty Tuple, written as().
2. Example #
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}Logic Explanation:
This example demonstrates how to use a Tuple to return both a minimum and maximum value at once. Additionally, the return type is marked as (min: Int, max: Int)?, indicating it is an “Optional Tuple”, allowing it to return nil if the array is empty.
3. C# #
Concept Mapping: C# 7.0 introduced ValueTuple, which is very similar.
C# Example:
// C# 7.0+ Tuple syntax
public (int min, int max)? MinMax(int[] array) {
if (array.Length == 0) return null;
int currentMin = array[0];
int currentMax = array[0];
foreach (var value in array.Skip(1)) {
if (value < currentMin) currentMin = value;
else if (value > currentMax) currentMax = value;
}
return (currentMin, currentMax);
}Key Differences Analysis:
- Syntax: Both syntaxes are similar. Swift’s
Voidcorresponds to C#’svoid, but Swift’sVoidis fundamentally an empty Tuple(), whereas C#’svoidis not a type that can be passed around. - Behavior: Note that Swift’s Optional Tuple
(Int, Int)?means the entire Tuple might not exist; this is different from a Tuple containing Optionals(Int?, Int?). C#’sNullable<(int, int)>behaves similarly to the former.
Functions With an Implicit Return #
1. Core Concepts #
- Concept Explanation: If the entire body of the function consists of a
single expression, thereturnkeyword can be omitted.
2. Example #
func greeting(for person: String) -> String {
"Hello, " + person + "!"
}Logic Explanation: The compiler automatically treats the result of the last line as the return value, making the code more concise.
3. C# #
Concept Mapping: Equivalent to C#’s Expression-bodied members.
C# Example:
public string Greeting(string person) => "Hello, " + person + "!";Key Differences Analysis:
- Syntax: C# uses the lambda arrow
=>; Swift keeps the curly braces{}but omitsreturn.
Function Argument Labels and Parameter Names #
1. Core Concepts #
- Concept Explanation: This is one of Swift’s most distinctive features. Each parameter has two names:
- Argument Label: Used when calling the function, aiming to make the call site read like natural language.
- Parameter Name: Used within the implementation of the function.
- Key Syntax:
ArgumentLabel ParameterName: Type,_(omit label)
2. Example #
// Specific label: 'from' used at call site, 'hometown' used internally
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Omit label: using _
func someFunction(_ firstParameterName: Int, secondParameterName: Int) { ... }
someFunction(1, secondParameterName: 2)Logic Explanation:
The greet function uses from so that the call greet(..., from: "Cupertino") reads very fluently. If you do not wish to enforce a label, you can use an underscore _ to omit it, which is useful when mimicking C-style libraries.
3. C# #
Concept Mapping: C# does not have a direct equivalent for this “split naming” mechanism.
C# Example:
// C# cannot fully simulate Swift's "from hometown" syntax
// Can only rely on parameter naming to convey semantics
public string Greet(string person, string from) {
return $"Hello {person}! Glad you could visit from {from}.";
}
// Call
Greet(person: "Bill", from: "Cupertino");Key Differences Analysis:
- Syntax: Swift allows
func f(label name: Type), while C# only hasvoid f(Type name). - Design Philosophy: Swift emphasizes Call-site readability, regarding “reading like an English sentence” as a guiding principle.
Default Parameter Values #
1. Core Concepts #
- Concept Explanation: You can provide default values for parameters in the function definition. If that parameter is omitted during the call, the default value is used.
- Key Syntax:
param: Type = value
2. Example #
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
// ...
}
someFunction(parameterWithoutDefault: 4) // parameterWithDefault uses 123. C# #
Concept Mapping: Fully corresponds to C#’s Optional Arguments.
C# Example:
void SomeFunction(int parameterWithoutDefault, int parameterWithDefault = 12) { ... }Key Differences Analysis:
- Behavior: The mechanisms are nearly identical. However, in Swift, it is generally recommended to place parameters with default values at the end (though Swift syntax doesn’t enforce it, it is a good habit), which aligns with C#’s rule (optional parameters must appear after required parameters).
Variadic Parameters #
1. Core Concepts #
- Concept Explanation: Allows a function to accept zero or more values of a specific type.
- Key Syntax:
Type...
2. Example #
func arithmeticMean(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)Logic Explanation:
Internally, numbers is treated as an array of type [Double].
3. C# #
Concept Mapping: Corresponds to the params keyword in C#.
C# Example:
public double ArithmeticMean(params double[] numbers) {
double total = 0;
foreach (var number in numbers) {
total += number;
}
return total / numbers.Length;
}Key Differences Analysis:
- Syntax: Swift uses the suffix
...; C# uses the prefixparamskeyword.
In-Out Parameters #
1. Core Concepts #
- Concept Explanation: By default, Swift function parameters are constants, meaning they cannot be modified inside the function. If you need to modify a passed variable and have the changes persist, use
inout. - Key Syntax:
inout,& - Note:
In-out parameters cannot have default values, and variadic parameters cannot be marked as
inout.
2. Example #
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)Logic Explanation:
The inout keyword indicates the parameter can be modified. When calling, you must prefix the variable with an & symbol, where & signifies “allow this parameter to be modified by the function and written back” (Copy-in Copy-out).
3. C# #
Concept Mapping: Corresponds to the ref keyword in C#.
C# Example:
public void SwapTwoInts(ref int a, ref int b) {
int temporaryA = a;
a = b;
b = temporaryA;
}
int someInt = 3;
int anotherInt = 107;
SwapTwoInts(ref someInt, ref anotherInt);Key Differences Analysis:
- Syntax: Swift uses
inoutat definition and&at call; C# usesreffor both definition and call. - Behavior: The concepts are consistent—both allow Value Types (like Struct, Int) to be modified like Reference Types. Note that Swift’s
inoutbehavior relies on “Copy-in Copy-out” optimization at the low level, which differs slightly from C#’s direct memory reference (ref), but for general usage, they can be treated as the same.
Function Types #
1. Core Concepts #
- Concept Explanation: In Swift, functions are First-class citizens. A function itself has a type and can be assigned to a variable, passed as a parameter, or returned as a value.
- Key Syntax:
(ParamTypes) -> ReturnType
2. Example #
func addTwoInts(_ a: Int, _ b: Int) -> Int { a + b }
// Define variable mathFunction, typed as "a function taking two Ints and returning an Int"
var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))")
// Function as a parameter
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)Logic Explanation:
The mathFunction variable stores a reference to the addTwoInts function. This allows you to dynamically swap execution logic.
3. C# #
Concept Mapping: Corresponds to C# Delegates (Func<>, Action<>).
C# Example:
int AddTwoInts(int a, int b) => a + b;
// Using Func delegate
Func<int, int, int> mathFunction = AddTwoInts;
Console.WriteLine($"Result: {mathFunction(2, 3)}");
// Function as a parameter
public void PrintMathResult(Func<int, int, int> mathFunc, int a, int b) {
Console.WriteLine($"Result: {mathFunc(a, b)}");
}Key Differences Analysis:
- Behavior: Essentially the same; both serve as references to code blocks.
Nested Functions #
1. Core Concepts #
- Concept Explanation: You can define a function inside another function. The inner function can access variables from the outer function (closure property) and can be returned for external use.
- Key Syntax: Function scope
2. Example #
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}Logic Explanation:
stepForward and stepBackward are hidden inside chooseStepFunction, keeping the global namespace clean. External code cannot call them directly, but they can be passed out as return values.
3. C# #
Concept Mapping: Corresponds to Local Functions introduced in C# 7.0.
C# Example:
public Func<int, int> ChooseStepFunction(bool backward) {
int StepForward(int input) => input + 1;
int StepBackward(int input) => input - 1;
return backward ? (Func<int, int>)StepBackward : StepForward;
}Key Differences Analysis:
- Syntax: Structure is almost identical.
- Behavior: Both support Closure characteristics, meaning the inner function can capture the variable state of the outer function. This is effective for encapsulating helper functions when writing complex algorithms or recursive logic.