mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 17:41:41 +00:00
Mark Zig code as zig
This commit is contained in:
parent
c2878077cb
commit
f9e182b42b
@ -5,24 +5,19 @@ contributors:
|
||||
- ["Philippe Pittoli", "https://karchnu.fr/"]
|
||||
---
|
||||
|
||||
|
||||
[Zig][ziglang] aims to be a replacement for the C programming language.
|
||||
|
||||
**WARNING**: this document expects you to understand a few basic concepts in computer science, such as pointers, stack and heap memory, etc.
|
||||
|
||||
**WARNING**: Zig isn't considered as ready for production. Bugs are expected.
|
||||
DO NOT TRY ZIG AS YOUR FIRST PROGRAMMING EXPERIENCE.
|
||||
The compiler, even the language and its libraries aren't ready, yet.
|
||||
You've been warned.
|
||||
|
||||
Prior knowledge of C is recommended.
|
||||
|
||||
|
||||
## Quick overview: Zig compared to C
|
||||
|
||||
- Syntax is mostly the same, with some improvements (less ambiguity).
|
||||
- Zig introduces namespaces.
|
||||
- Try and catch mechanism, which is both convenient, efficient and optional.
|
||||
- `try` and `catch` mechanism, which is both convenient, efficient and optional.
|
||||
- Most of the C undefined behaviors (UBs) are fixed.
|
||||
- Compared to C, raw pointers are safer to use and less likely to be needed.
|
||||
* The type system distinguishes between a pointer to a single value, or multiple values, etc.
|
||||
@ -38,8 +33,7 @@ Prior knowledge of C is recommended.
|
||||
|
||||
## Zig language
|
||||
|
||||
|
||||
```
|
||||
```zig
|
||||
//! Top-level documentation.
|
||||
|
||||
/// Documentation comment.
|
||||
@ -47,9 +41,9 @@ Prior knowledge of C is recommended.
|
||||
// Simple comment.
|
||||
```
|
||||
|
||||
|
||||
### Hello world.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Import standard library, reachable through the "std" constant.
|
||||
const std = @import("std");
|
||||
|
||||
@ -67,7 +61,8 @@ pub fn main() void {
|
||||
```
|
||||
|
||||
### Booleans, integers and float.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Booleans.
|
||||
// Keywords are preferred to operators for boolean operations.
|
||||
print("{}\n{}\n{}\n", .{
|
||||
@ -109,7 +104,8 @@ i <<| 8 == 255 // u8: won't go higher than 255
|
||||
```
|
||||
|
||||
### Arrays.
|
||||
```
|
||||
|
||||
```zig
|
||||
// An array is a well-defined structure with a length attribute (len).
|
||||
|
||||
// 5-byte array with undefined content (stack garbage).
|
||||
@ -156,8 +152,8 @@ try some_integers[i]; // Runtime error 'index out of bounds'.
|
||||
```
|
||||
|
||||
### Multidimensional arrays.
|
||||
```
|
||||
|
||||
```zig
|
||||
const mat4x4 = [4][4]f32{
|
||||
[_]f32{ 1.0, 0.0, 0.0, 0.0 },
|
||||
[_]f32{ 0.0, 1.0, 0.0, 1.0 },
|
||||
@ -177,8 +173,8 @@ for (mat4x4) |row, row_index| {
|
||||
```
|
||||
|
||||
### Strings.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Simple string constant.
|
||||
const greetings = "hello";
|
||||
// ... which is equivalent to:
|
||||
@ -195,8 +191,8 @@ print("string: {s}\n", .{greetings});
|
||||
```
|
||||
|
||||
### Slices.
|
||||
```
|
||||
|
||||
```zig
|
||||
// A slice is a pointer and a size, an array without compile-time known size.
|
||||
// Slices have runtime out-of-band verifications.
|
||||
|
||||
@ -206,8 +202,8 @@ const slice = array[0..array.len]; // "slice" represents the whole array.
|
||||
```
|
||||
|
||||
### Pointers.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Pointer on a value can be created with "&".
|
||||
const x: i32 = 1;
|
||||
const pointer: *i32 = &x; // "pointer" is a pointer on the i32 var "x".
|
||||
@ -223,7 +219,8 @@ const foo = pointer.?; // Get the pointed value, otherwise crash.
|
||||
```
|
||||
|
||||
### Optional values (?<type>).
|
||||
```
|
||||
|
||||
```zig
|
||||
// An optional is a value than can be of any type or null.
|
||||
|
||||
// Example: "optional_value" can either be "null" or an unsigned 32-bit integer.
|
||||
@ -239,7 +236,8 @@ if (x) |value| {
|
||||
```
|
||||
|
||||
### Errors.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Zig provides an unified way to express errors.
|
||||
|
||||
// Errors are defined in error enumerations, example:
|
||||
@ -299,7 +297,7 @@ var value = try some_function();
|
||||
|
||||
### Control flow.
|
||||
|
||||
```
|
||||
```zig
|
||||
// Conditional branching.
|
||||
|
||||
if (condition) {
|
||||
@ -384,8 +382,8 @@ const result = for (items) |value| {
|
||||
```
|
||||
|
||||
### Labels.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Labels are a way to name an instruction, a location in the code.
|
||||
// Labels can be used to "continue" or "break" in a nested loop.
|
||||
outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| {
|
||||
@ -434,8 +432,8 @@ const result = for (items) |value| { // First: loop.
|
||||
```
|
||||
|
||||
### Switch.
|
||||
```
|
||||
|
||||
```zig
|
||||
// As a switch in C, but slightly more advanced.
|
||||
// Syntax:
|
||||
// switch (value) {
|
||||
@ -454,15 +452,15 @@ var x = switch(value) {
|
||||
// A slightly more advanced switch, accepting a range of values:
|
||||
const foo: i32 = 0;
|
||||
const bar = switch (foo) {
|
||||
0 => "zero",
|
||||
1...std.math.maxInt(i32) => "positive",
|
||||
else => "negative",
|
||||
0 => "zero",
|
||||
1...std.math.maxInt(i32) => "positive",
|
||||
else => "negative",
|
||||
};
|
||||
```
|
||||
|
||||
### Structures.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Structure containing a single value.
|
||||
const Full = struct {
|
||||
number: u16,
|
||||
@ -564,7 +562,8 @@ print("p.y: {}\n", .{p.y}); // 30
|
||||
```
|
||||
|
||||
### Tuples.
|
||||
```
|
||||
|
||||
```zig
|
||||
// A tuple is a list of elements, possibly of different types.
|
||||
|
||||
const foo = .{ "hello", true, 42 };
|
||||
@ -572,33 +571,33 @@ const foo = .{ "hello", true, 42 };
|
||||
```
|
||||
|
||||
### Enumerations.
|
||||
```
|
||||
|
||||
```zig
|
||||
const Type = enum { ok, not_ok };
|
||||
|
||||
const CardinalDirections = enum { North, South, East, West };
|
||||
const direction: CardinalDirections = .North;
|
||||
const x = switch (direction) {
|
||||
// shorthand for CardinalDirections.North
|
||||
.North => true,
|
||||
else => false
|
||||
// shorthand for CardinalDirections.North
|
||||
.North => true,
|
||||
else => false
|
||||
};
|
||||
|
||||
// Switch statements need exhaustiveness.
|
||||
// WARNING: won't compile. East and West are missing.
|
||||
const x = switch (direction) {
|
||||
.North => true,
|
||||
.South => true,
|
||||
.North => true,
|
||||
.South => true,
|
||||
};
|
||||
|
||||
|
||||
// Switch statements need exhaustiveness.
|
||||
// Won't compile: East and West are missing.
|
||||
const x = switch (direction) {
|
||||
.North => true,
|
||||
.South => true,
|
||||
.East, // Its value is the same as the following pattern: false.
|
||||
.West => false,
|
||||
.North => true,
|
||||
.South => true,
|
||||
.East, // Its value is the same as the following pattern: false.
|
||||
.West => false,
|
||||
};
|
||||
|
||||
|
||||
@ -606,12 +605,12 @@ const x = switch (direction) {
|
||||
```
|
||||
|
||||
### Unions.
|
||||
```
|
||||
|
||||
```zig
|
||||
const Bar = union {
|
||||
boolean: bool,
|
||||
int: i16,
|
||||
float: f32,
|
||||
boolean: bool,
|
||||
int: i16,
|
||||
float: f32,
|
||||
};
|
||||
|
||||
// Both syntaxes are equivalent.
|
||||
@ -622,8 +621,8 @@ const foo: Bar = .{ .int = 42 };
|
||||
```
|
||||
|
||||
### Tagged unions.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Unions can be declared with an enum tag type, allowing them to be used in
|
||||
// switch expressions.
|
||||
|
||||
@ -653,8 +652,8 @@ switch (nay) {
|
||||
```
|
||||
|
||||
### Defer and errdefer.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Make sure that an action (single instruction or block of code) is executed
|
||||
// before the end of the scope (function, block of code).
|
||||
// Even on error, that action will be executed.
|
||||
@ -695,24 +694,25 @@ Thus, the standard library lets developers handle memory as they need, through s
|
||||
**NOTE**: the choice of the allocator isn't in the scope of this document.
|
||||
A whole book could be written about it.
|
||||
However, here are some examples, to get an idea of what you can expect:
|
||||
- page_allocator.
|
||||
- `page_allocator`.
|
||||
Allocate a whole page of memory each time we ask for some memory.
|
||||
Very simple, very dumb, very wasteful.
|
||||
- GeneralPurposeAllocator.
|
||||
- `GeneralPurposeAllocator`.
|
||||
Get some memory first and manage some buckets of memory in order to
|
||||
reduce the number of allocations.
|
||||
A bit complex. Can be combined with other allocators.
|
||||
Can detect leaks and provide useful information to find them.
|
||||
- FixedBufferAllocator.
|
||||
- `FixedBufferAllocator`.
|
||||
Use a fixed buffer to get its memory, don't ask memory to the kernel.
|
||||
Very simple, limited and wasteful (can't deallocate), but very fast.
|
||||
- ArenaAllocator.
|
||||
- `ArenaAllocator`.
|
||||
Allow to free all allocated memory at once.
|
||||
To use in combinations with another allocator.
|
||||
Very simple way of avoiding leaks.
|
||||
|
||||
A first example.
|
||||
```
|
||||
|
||||
```zig
|
||||
// "!void" means the function doesn't return any value except for errors.
|
||||
// In this case we try to allocate memory, and this may fail.
|
||||
fn foo() !void {
|
||||
@ -735,8 +735,8 @@ fn foo() !void {
|
||||
```
|
||||
|
||||
### Memory allocation combined with error management and defer.
|
||||
```
|
||||
|
||||
```zig
|
||||
fn some_memory_allocation_example() !void {
|
||||
// Memory allocation may fail, so we "try" to allocate the memory and
|
||||
// in case there is an error, the current function returns it.
|
||||
@ -759,8 +759,8 @@ fn some_memory_allocation_example() !void {
|
||||
```
|
||||
|
||||
### Memory allocators: a taste of the standard library.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Allocators: 4 main functions to know
|
||||
// single_value = create (type)
|
||||
// destroy (single_value)
|
||||
@ -846,8 +846,8 @@ fn gpa_arena_allocator_fn() !void {
|
||||
```
|
||||
|
||||
### Comptime.
|
||||
```
|
||||
|
||||
```zig
|
||||
// Comptime is a way to avoid the pre-processor.
|
||||
// The idea is simple: run code at compilation.
|
||||
|
||||
@ -883,7 +883,8 @@ list.items[0] = 10;
|
||||
```
|
||||
|
||||
### Conditional compilation.
|
||||
```
|
||||
|
||||
```zig
|
||||
const available_os = enum { OpenBSD, Linux };
|
||||
const myos = available_os.OpenBSD;
|
||||
|
||||
@ -905,7 +906,8 @@ const myprint = switch(myos) {
|
||||
```
|
||||
|
||||
### Testing our functions.
|
||||
```
|
||||
|
||||
```zig
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
@ -936,45 +938,44 @@ There are more than a hundred built-ins, allowing very low-level stuff:
|
||||
- etc.
|
||||
|
||||
Example: enums aren't integers, they have to be converted with a built-in.
|
||||
```
|
||||
|
||||
```zig
|
||||
const Value = enum { zero, stuff, blah };
|
||||
if (@enumToInt(Value.zero) == 0) { ... }
|
||||
if (@enumToInt(Value.stuff) == 1) { ... }
|
||||
if (@enumToInt(Value.blah) == 2) { ... }
|
||||
```
|
||||
|
||||
|
||||
### A few "not yourself in the foot" measures in the Zig language.
|
||||
|
||||
- Namespaces: names conflicts are easily avoided.
|
||||
In practice, that means an unified API between different structures (data types).
|
||||
- Namespaces: name conflicts are easily avoided.
|
||||
In practice, that means a unified API between different structures (data types).
|
||||
- Enumerations aren't integers. Comparing an enumeration to an integer requires a conversion.
|
||||
- Explicit casts, coercion exists but is limited.
|
||||
Types are slightly more enforced than in C, just a taste:
|
||||
Pointers aren't integers, explicit conversion is necessary.
|
||||
You won't lose precision by accident, implicit coercions are only authorized in case no precision can be lost.
|
||||
Unions cannot be reinterpreted (in an union with an integer and a float, one cannot take a value for another by accident).
|
||||
You won't lose precision by accident, implicit coercions are only authorized in cases where no precision can be lost.
|
||||
Unions cannot be reinterpreted (in a union with an integer and a float, one cannot take a value for another by accident).
|
||||
Etc.
|
||||
- Removing most of the C undefined behaviors (UBs), and when the compiler encounters one, it stops.
|
||||
- Slice and Array structures are preferred to pointers.
|
||||
Types enforced by the compiler are less prone to errors than pointer manipulations.
|
||||
- Numerical overflows produce an error, unless explicitly accepted using wrapping operators.
|
||||
- Try and catch mechanism.
|
||||
- `try` and `catch` mechanism.
|
||||
It's both handy, trivially implemented (simple error enumeration), and it takes almost no space nor computation time.
|
||||
- Unused variables are considered as errors by the compiler.
|
||||
- Many pointer types exist in order to represent what is pointed.
|
||||
- Unused variables are considered to be errors by the compiler.
|
||||
- Many pointer types exist in order to represent what is pointed to.
|
||||
Example: is this a single value or an array, is the length known, etc.
|
||||
- Structures need a value for their attributes, and it still is possible to give an undefined value (stack garbage), but at least it is explicitly undefined.
|
||||
- Structures need a value for their attributes, and it is still possible to give an undefined value (stack garbage), but at least it is explicitly undefined.
|
||||
|
||||
|
||||
## Further Reading
|
||||
|
||||
For a start, some concepts are presented on the [Zig learn website][ziglearn].
|
||||
For a start, some concepts are presented on [zig.guide][zigguide].
|
||||
|
||||
The [official website][zigdoc] provides a reference documentation to the language.
|
||||
|
||||
For now, documentation for standard library is WIP.
|
||||
The [official website][zigdoc] provides the reference documentation of the language. The standard library [has its own documentation][zigstd].
|
||||
|
||||
[ziglang]: https://ziglang.org
|
||||
[ziglearn]: https://ziglearn.org/
|
||||
[zigguide]: https://zig.guide/
|
||||
[zigdoc]: https://ziglang.org/documentation/
|
||||
[zigstd]: https://ziglang.org/documentation/master/std/
|
||||
|
Loading…
Reference in New Issue
Block a user