Einführung in die funktionale Programmierung in Swift
Swift ist eine multiparadigmatische Programmiersprache, die von Apple für die Entwicklung von Anwendungen für iOS, macOS, watchOS und tvOS entwickelt wurde. Neben objektorientierten und protokollorientierten Ansätzen unterstützt Swift aktiv funktionale Programmierung. Dieser Stil basiert auf der Verwendung reiner Funktionen, der Unveränderlichkeit von Daten und dem Verzicht auf Seiteneffekte.
Funktionale Programmierung macht Code vorhersagbarer, testbarer und parallel sicherer. In diesem Artikel werden wir die wichtigsten Konzepte des funktionalen Ansatzes in Swift behandeln: Unveränderlichkeit, Funktionen höherer Ordnung, Closures und Method Chains. Sie werden sehen, wie Sie mit map, filter und reduce prägnanten und ausdrucksstarken Code schreiben können.
Grundlagen des funktionalen Ansatzes in Swift
Unveränderlichkeit (Immutability)
In der funktionalen Programmierung werden Daten nach ihrer Erstellung nicht verändert. Anstatt ein vorhandenes Objekt zu ändern, wird ein neues erstellt. Swift fördert diesen Ansatz mit dem Schlüsselwort let zur Deklaration von Konstanten.
// Unveränderlicher Wertlet numbers = [1, 2, 3, 4, 5]// numbers.append(6) // Compiler-Fehler — numbers ist unveränderlich
// Erstellen eines neuen Arrayslet newNumbers = numbers + [6]print(newNumbers) // [1, 2, 3, 4, 5, 6]Die Verwendung von let anstelle von var hilft, versehentliche Zustandsänderungen zu vermeiden und vereinfacht das Debugging.
Funktionen als First-Class-Objekte
In Swift sind Funktionen First-Class-Objekte. Sie können Variablen zugewiesen, als Argumente übergeben und von anderen Funktionen zurückgegeben werden.
// Einer Variablen zugewiesene Funktionlet multiply: (Int, Int) -> Int = { $0 * $1 }print(multiply(3, 4)) // 12
// Funktion, die eine andere Funktion akzeptiertfunc applyOperation(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int { return operation(a, b)}
let result = applyOperation(10, 5, operation: multiply)print(result) // 50Closures in Swift
Closures sind in sich geschlossene Funktionsblöcke, die Referenzen auf Variablen aus dem umgebenden Kontext erfassen und speichern können. In Swift werden Closures häufig für Callbacks und funktionale Transformationen verwendet.
// Einfaches Closurelet greeting = { (name: String) -> String in return "Hallo, \\(name)!"}print(greeting("Welt")) // Hallo, Welt!
// Kurzform mit Parameternlet numbers = [3, 1, 4, 1, 5, 9]let sorted = numbers.sorted { $0 < $1 }print(sorted) // [1, 1, 3, 4, 5, 9]Closures machen Code kompakt und ausdrucksstark, insbesondere bei der Arbeit mit Collections.
Funktionen höherer Ordnung: map, filter, reduce
Dies sind die drei Säulen der funktionalen Programmierung in Swift. Sie ermöglichen die Verarbeitung von Arrays, Dictionaries und anderen Collections ohne explizite Schleifen.
map — Transformation jedes Elements
Die Methode map wendet ein Closure auf jedes Element einer Collection an und gibt ein neues Array mit den Ergebnissen zurück.
let prices = [100, 200, 300, 400]let discounted = prices.map { $0 * 0.9 }print(discounted) // [90.0, 180.0, 270.0, 360.0]
// Arbeiten mit Stringslet names = ["Anna", "Boris", "Viktor"]let uppercased = names.map { $0.uppercased() }print(uppercased) // ["ANNA", "BORIS", "VIKTOR"]filter — Auswahl nach Bedingung
filter gibt ein neues Array zurück, das nur die Elemente enthält, die eine bestimmte Bedingung erfüllen.
let scores = [45, 78, 92, 33, 88, 61]let passingScores = scores.filter { $0 >= 60 }print(passingScores) // [78, 92, 88, 61]
// Filtern von Stringslet words = ["Swift", "iOS", "macOS", "Funktion"]let shortWords = words.filter { $0.count <= 4 }print(shortWords) // ["iOS", "macOS"]