- Zig basiert wie Rust auf einer geschweiften Klammern basierten Syntax, verbessert sie jedoch durch einfachere Sprachsemantik und elegantere Syntaxentscheidungen
- Integer-Literale beginnen unabhängig vom Typ als
comptime_int und werden bei der Zuweisung explizit konvertiert, während String-Literale eine kompakte Raw-String-Notation auf Basis von \\ verwenden
- Record-Literale in der Form
.x = 1 machen Feldzuweisungen leichter durchsuchbar, und alle Typen werden konsistent in Präfixnotation dargestellt
and und or werden als Schlüsselwörter für den Kontrollfluss verwendet, und bei if- und **loop-**Konstrukten können geschweifte Klammern optional entfallen, wobei der Formatter die Sicherheit gewährleistet
- Ohne Namespaces wird alles als Ausdruck behandelt, wodurch die Syntax für Typen, Werte und Muster vereinheitlicht wird und Generics, Record-Literale sowie Built-ins (
@import, @as usw.) kompakt genutzt werden können
Überblick
- Zig hat eine Rust ähnliche äußere Form, setzt aber auf eine einfachere Sprachstruktur
- Beim Syntaxdesign liegt der Fokus auf grep-Freundlichkeit, syntaktischer Konsistenz und der Reduzierung unnötigen visuellen Rauschens
Integer-Literale
const an_integer = 92;
assert(@TypeOf(an_integer) == comptime_int);
const x: i32 = 92;
const y = @as(i32, 92);
- Alle Integer-Literale haben den Typ
comptime_int
- Bei der Zuweisung an Variablen wird der Typ explizit angegeben oder per
@as konvertiert
- Die Form
var x = 92; funktioniert nicht; ein expliziter Typ ist erforderlich
String-Literale
const raw =
\\Roses are red
\\ Violets are blue,
\\Sugar is sweet
\\ And so are you.
\\
;
- Jede Zeile ist ein eigenes Token, daher gibt es keine Einrückungsprobleme
\\ selbst muss nicht escaped werden
Record-Literale
const p: Point = .{
.x = 1,
.y = 2,
};
- Das Format
.x = 1 ist vorteilhaft, um Lesen und Schreiben zu unterscheiden
- Die Schreibweise
.{} grenzt sich von Blöcken ab und wird automatisch in den Ergebnistyp umgewandelt
Typnotation
u32 // Integer
[3]u32 // Array der Länge 3
?[3]u32 // nullbares Array
*const ?[3]u32 // konstanter Zeiger
- Alle Typen verwenden Präfixnotation
- Die Dereferenzierung verwendet Suffixnotation (
ptr.*)
Bezeichner
const @"a name with space" = 42;
- Verhindert Konflikte mit Schlüsselwörtern oder erlaubt spezielle Namen
Funktionsdeklaration
pub fn main() void {}
fn add(x: i32, y: i32) i32 {
return x + y;
}
- Das Schlüsselwort
fn und der Funktionsname stehen zusammen, was die Suche erleichtert
- Für die Angabe des Rückgabetyps wird kein
-> verwendet
Variablendeklaration
const mid = lo + @divFloor(hi - lo, 2);
var count: u32 = 0;
- Verwendet
const und var
- Die Typangabe folgt der Reihenfolge
Name: Typ
Kontrollfluss: and/or
while (count > 0 and ascii.isWhitespace(buffer[count - 1])) {
count -= 1;
}
and und or sind Schlüsselwörter für den Kontrollfluss
- Für Bit-Operationen werden
& und | verwendet
if-Anweisung
.direction = if (prng.boolean()) .ascending else .descending;
- Klammern sind Pflicht, geschweifte Klammern optional
zig fmt garantiert ein sicheres Formatting
Schleifen
for (0..10) |i| {
print("{d}\n", .{i});
} else @panic("loop safety counter exceeded");
- Sowohl
for als auch while unterstützen einen else-Zweig
- Iterator und Elementname sind intuitiv angeordnet
Namespaces und Namensauflösung
const std = @import("std");
const ArrayList = std.ArrayList;
- Shadowing von Variablen ist verboten
- Es gibt weder Namespaces noch Glob-Imports
Alles ist ein Ausdruck
const E = enum { a, b };
const e: if (true) E else void = .a;
- Die Syntax für Typen, Werte und Muster wird vereinheitlicht
- Ein bedingter Ausdruck kann an einer Typ-Position stehen
Generics
fn ArrayListType(comptime T: type) type {
return struct {
fn init() void {}
};
}
var xs: ArrayListType(u32) = .init();
- Generics werden mit Funktionsaufrufsyntax (
Type(T)) ausgedrückt
- Typargumente sind immer explizit
Built-ins
const foo = @import("./foo.zig");
const num = @as(i32, 92);
- Mit dem Präfix
@ werden vom Compiler bereitgestellte Funktionen aufgerufen
@import zeigt den Dateipfad eindeutig an
- Argumente müssen zwingend String-Literale sein
Fazit
- Zigs Syntax ist ein Beispiel dafür, wie eine Sammlung kleiner Entscheidungen eine gut lesbare Sprache entstehen lässt
- Wenn die Anzahl der Features sinkt, sinkt auch der Bedarf an Syntax, und die Wahrscheinlichkeit syntaktischer Konflikte nimmt ebenfalls ab
- Gute Ideen aus bestehenden Sprachen werden übernommen, aber wenn nötig, werden mutig neue Syntaxformen eingeführt
Noch keine Kommentare.