Programmiersprache Swift 5.9 führt Makros und ein Ownership-Konzept ein
Das neue Makrosystem von Swift bietet mehr als die Textbausteine in C/C++. Ownership bietet ein Konzept, um die Speicherverwaltung zu optimieren.
Knapp sechs Monate nach Swift 5.8 ist Version 5.9 von Apples quelloffener Programmiersprache erschienen. Das aktuelle Release führt Makros ein und bekommt eine bidirektionale Anbindung an C++. Außerdem bringt sie erste Ansätze für das Ownership-Konzept, das als wesentlicher Bestandteil von Swift 6 vorgesehen ist.
Kurz und knapp formuliert
Makros ergänzen Teile des Quellcodes vor dem Kompilieren mit zuvor definierten Inhalten. Swift orientiert sich bei der Implementierung eher an dem Makrosystem von Rust als den einfachen Makros in C oder C++, bei denen Makros einfache Platzhalter für Textbausteine sind, die vor dem Kompilieren ersetzt werden.
Swift 5.9 kennt zwei Arten von Markos: freistehende (freestanding) und angebundene (attached). Erstere sind mit #
ausgezeichnet, und Swift ruft beim Kompilieren die Implementierung des Makros auf. Folgender Code verwendet das function()
-Makro aus der Standard-Library von Swift:
func myFunction(){
print ("Das Programm befindet sich in der Funktion \(#function)")
}
Das Makro ersetzt #function
durch den Funktionsnamen, womit obiger Code "Das Programm befindet sich in der Funktion myFunction()" ausgibt.
Attached Macros helfen unter anderem bei der Arbeit mit Swift-Protokollen, wie folgender Codeausschnitt aus der Swift-Dokumentation zeigt, der das OptionSet
-Protokoll mit einer Reihe von Konstanten automatisch befüllt:
// Makro-Variante
@OptionSet<Int>
struct SundaeToppings {
private enum Options: Int {
case nuts
case cherry
case fudge
}
}
// Manuelle Umsetzung ohne Makros
struct SundaeToppings: OptionSet {
let rawValue: Int
static let nuts = SundaeToppings(rawValue: 1 << 0)
static let cherry = SundaeToppings(rawValue: 1 << 1)
static let fudge = SundaeToppings(rawValue: 1 << 2)
}
Zusammenspiel mit C++
Eine weitere wichtige Neuerung ist die bidirektionale Interoperabilität mit C++, mit der sich externe Funktionen direkt aus Swift heraus verwenden lassen, wie ein Beispiel aus dem Swift-Blog zeigt, das die C++-Funktion
// Clang module 'PromptResponder'
#pragma once
#include <vector>
std::vector<std::string> generatePromptResponse(std::string prompt);
aus Swift aufruft:
import PromptResponder
let codeLines =
generatePromptResponse("Write Swift code that prints hello world")
.map(String.init)
.filter { !$0.isEmpty }
for line in codeLines {
print(line)
}
Geliehene Werte
Swift 5.9 führt zudem erste Ansätze eines Ownership-Konzepts für Variablen ein, das nicht so strikt und grundlegend ist wie in Rust, aber beim Optimieren der Speicherverwaltung helfen soll. Unter anderem entfällt damit die Notwendigkeit, die einzelnen Referenzen der Werte zu zählen. Der neue Operator consume
erklärt die Lebenszeit einer Variable als beendet, sodass beim Zuweisen die alte Variable ihre Gültigkeit verliert. Nach der Anweisung
let b = consume a
enthält b
den Wert von a
, und anschließende Versuche, auf a
zuzugreifen, lösen einen Fehler aus. Mit dem Operator lässt sich auch eine Variable mit
_ = consume a
explizit freigeben, ohne den Wert einer anderen zuzuweisen. Parameter können neuerdings als borrowing
oder consuming
deklariert werden. Außerdem führt Swift 5.9 nicht kopierbare Structs und Enums ein.
Weitere Neuerungen in Swift 5.9 wie Parameter Packs zum Übergeben einer flexiblen Zahl von Parametern und direkte Variablen-Zuweisungen in If- und Switch-Anweisungen lassen sich dem Swift-Blog entnehmen.
Zu der weiteren Roadmap der kommenden Hauptversion, die bereits in Swift 5.8 ihre Schatten vorausgeworfen hat, finden sich keine Angaben im Blogbeitrag.
(rme)