Initial
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| .vscode/ | ||||
| zig-*/ | ||||
| .zig-*/ | ||||
							
								
								
									
										7
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| See [talk notes](talk.md) | ||||
|  | ||||
| To run `zig build run` | ||||
|  | ||||
| To build C samples, run: | ||||
| - `zig cc c\string_append_or.c -o "bin\string_append_or.exe"` | ||||
| - `zig cc c\malloc.c -o "bin\malloc.exe"` | ||||
							
								
								
									
										47
									
								
								build.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								build.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| const std = @import("std"); | ||||
|  | ||||
| pub fn build(b: *std.Build) void { | ||||
|     const target = b.standardTargetOptions(.{}); | ||||
|     const optimize = b.standardOptimizeOption(.{}); | ||||
|  | ||||
|     const exe = b.addExecutable(.{ | ||||
|         .name = "decentrala-live", | ||||
|         .root_source_file = b.path("src/main.zig"), | ||||
|         .target = target, | ||||
|         .optimize = optimize, | ||||
|     }); | ||||
|  | ||||
|     b.installArtifact(exe); | ||||
|  | ||||
|     const run_cmd = b.addRunArtifact(exe); | ||||
|  | ||||
|     run_cmd.step.dependOn(b.getInstallStep()); | ||||
|  | ||||
|     if (b.args) |args| { | ||||
|         run_cmd.addArgs(args); | ||||
|     } | ||||
|  | ||||
|     const run_step = b.step("run", "Run the app"); | ||||
|     run_step.dependOn(&run_cmd.step); | ||||
|  | ||||
|     const exe_unit_tests = b.addTest(.{ | ||||
|         .root_source_file = b.path("src/main.zig"), | ||||
|         .target = target, | ||||
|         .optimize = optimize, | ||||
|     }); | ||||
|  | ||||
|     const exe_check = b.addExecutable(.{ | ||||
|         .name = "check_step", | ||||
|         .root_source_file = b.path("src/main.zig"), | ||||
|         .target = target, | ||||
|         .optimize = optimize, | ||||
|     }); | ||||
|  | ||||
|     const check = b.step("check", "Check if project compiles"); | ||||
|     check.dependOn(&exe_check.step); | ||||
|  | ||||
|     const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); | ||||
|  | ||||
|     const test_step = b.step("test", "Run unit tests"); | ||||
|     test_step.dependOn(&run_exe_unit_tests.step); | ||||
| } | ||||
							
								
								
									
										72
									
								
								build.zig.zon
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								build.zig.zon
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| .{ | ||||
|     // This is the default name used by packages depending on this one. For | ||||
|     // example, when a user runs `zig fetch --save <url>`, this field is used | ||||
|     // as the key in the `dependencies` table. Although the user can choose a | ||||
|     // different name, most users will stick with this provided value. | ||||
|     // | ||||
|     // It is redundant to include "zig" in this name because it is already | ||||
|     // within the Zig package namespace. | ||||
|     .name = "decentrala-intro-talk", | ||||
|  | ||||
|     // This is a [Semantic Version](https://semver.org/). | ||||
|     // In a future version of Zig it will be used for package deduplication. | ||||
|     .version = "0.0.0", | ||||
|  | ||||
|     // This field is optional. | ||||
|     // This is currently advisory only; Zig does not yet do anything | ||||
|     // with this value. | ||||
|     //.minimum_zig_version = "0.11.0", | ||||
|  | ||||
|     // This field is optional. | ||||
|     // Each dependency must either provide a `url` and `hash`, or a `path`. | ||||
|     // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. | ||||
|     // Once all dependencies are fetched, `zig build` no longer requires | ||||
|     // internet connectivity. | ||||
|     .dependencies = .{ | ||||
|         // See `zig fetch --save <url>` for a command-line interface for adding dependencies. | ||||
|         //.example = .{ | ||||
|         //    // When updating this field to a new URL, be sure to delete the corresponding | ||||
|         //    // `hash`, otherwise you are communicating that you expect to find the old hash at | ||||
|         //    // the new URL. | ||||
|         //    .url = "https://example.com/foo.tar.gz", | ||||
|         // | ||||
|         //    // This is computed from the file contents of the directory of files that is | ||||
|         //    // obtained after fetching `url` and applying the inclusion rules given by | ||||
|         //    // `paths`. | ||||
|         //    // | ||||
|         //    // This field is the source of truth; packages do not come from a `url`; they | ||||
|         //    // come from a `hash`. `url` is just one of many possible mirrors for how to | ||||
|         //    // obtain a package matching this `hash`. | ||||
|         //    // | ||||
|         //    // Uses the [multihash](https://multiformats.io/multihash/) format. | ||||
|         //    .hash = "...", | ||||
|         // | ||||
|         //    // When this is provided, the package is found in a directory relative to the | ||||
|         //    // build root. In this case the package's hash is irrelevant and therefore not | ||||
|         //    // computed. This field and `url` are mutually exclusive. | ||||
|         //    .path = "foo", | ||||
|  | ||||
|         //    // When this is set to `true`, a package is declared to be lazily | ||||
|         //    // fetched. This makes the dependency only get fetched if it is | ||||
|         //    // actually used. | ||||
|         //    .lazy = false, | ||||
|         //}, | ||||
|     }, | ||||
|  | ||||
|     // Specifies the set of files and directories that are included in this package. | ||||
|     // Only files and directories listed here are included in the `hash` that | ||||
|     // is computed for this package. Only files listed here will remain on disk | ||||
|     // when using the zig package manager. As a rule of thumb, one should list | ||||
|     // files required for compilation plus any license(s). | ||||
|     // Paths are relative to the build root. Use the empty string (`""`) to refer to | ||||
|     // the build root itself. | ||||
|     // A directory listed here means that all files within, recursively, are included. | ||||
|     .paths = .{ | ||||
|         "build.zig", | ||||
|         "build.zig.zon", | ||||
|         "src", | ||||
|         // For example... | ||||
|         //"LICENSE", | ||||
|         //"README.md", | ||||
|     }, | ||||
| } | ||||
							
								
								
									
										9
									
								
								c/malloc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								c/malloc.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #include <stdlib.h> | ||||
|  | ||||
| int main() { | ||||
|     int* ptr = malloc(sizeof(int)); | ||||
|  | ||||
|     *ptr = 4; | ||||
|  | ||||
|     free(ptr); | ||||
| } | ||||
							
								
								
									
										27
									
								
								c/raii.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								c/raii.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
|  | ||||
| class MyClass | ||||
| { | ||||
| public: | ||||
|     void* ptr; | ||||
|  | ||||
|     MyClass() | ||||
|     { | ||||
|         ptr = malloc(sizeof(100000000)); | ||||
|     } | ||||
|  | ||||
|     ~MyClass() | ||||
|     { | ||||
|         free(ptr); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| MyClass myClass; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     std::vector<MyClass> vec; | ||||
|     vec.push_back({}); | ||||
|  | ||||
| } | ||||
							
								
								
									
										8
									
								
								c/string_append_or.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								c/string_append_or.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #include <stdio.h> | ||||
|  | ||||
| int main() { | ||||
|     for (size_t i = 0; i < 5; i++) | ||||
|     { | ||||
|         printf("Number is: " + i); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/main.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| const std = @import("std"); | ||||
|  | ||||
| fn calc(a: i32) i32 { | ||||
|     return a; | ||||
| } | ||||
|  | ||||
| const SOmethin = enum { | ||||
|     One, | ||||
|     Two, | ||||
|     Three, | ||||
| }; | ||||
|  | ||||
|  | ||||
| fn Optional(comptime T: type) type { | ||||
|     return struct { | ||||
|         valid: bool, | ||||
|         value: T, | ||||
|     }; | ||||
| } | ||||
|  | ||||
| fn add(a: anytype, b: anytype) @TypeOf(a + b) { | ||||
|     return a + b; | ||||
| } | ||||
|  | ||||
| const DivisionError = error{DivisionByZero}; | ||||
|  | ||||
| fn divide(a: f32, b: f32) !f32 { | ||||
|     if (b == 0) | ||||
|         return DivisionError.DivisionByZero; | ||||
|  | ||||
|     return a / b; | ||||
| } | ||||
|  | ||||
| pub fn main() !void { | ||||
|      | ||||
|  | ||||
|     std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); | ||||
|  | ||||
|     const vec = @Vector(4, i32){ 1, 0, 1, 0 }; | ||||
|     const vec2 = @Vector(4, i32){ 0, 1, 0, 1 }; | ||||
|  | ||||
|     std.debug.print("vec: {}", .{vec + vec2}); | ||||
| } | ||||
							
								
								
									
										126
									
								
								src/main2.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/main2.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | ||||
| const std = @import("std"); | ||||
| const Other = @import("other.zig"); | ||||
| const WRB = @import("rbuff.zig").WrappingRingBuffer; | ||||
|  | ||||
| const Vector2D = packed struct { | ||||
|     x: i5 = 2, | ||||
|     y: i23, | ||||
|  | ||||
|     fn name(self: Vector2D) void { | ||||
|         _ = self; // autofix | ||||
|  | ||||
|     } | ||||
|  | ||||
|     fn init() void {} | ||||
|     fn deinit() void {} | ||||
| }; | ||||
|  | ||||
| fn add(a: *i32, b: i32) i32 { | ||||
|     a.* = 3; | ||||
|     return a.* + b; | ||||
| } | ||||
|  | ||||
| const DivideError = error{ | ||||
|     DivivisionError, | ||||
| }; | ||||
|  | ||||
| fn divide(a: f32, b: f32) !f32 { | ||||
|     if (b == 0) { | ||||
|         return DivideError.DivivisionError; | ||||
|     } else { | ||||
|         return a / b; | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn Optional(comptime T: type) type { | ||||
|     return struct { | ||||
|         value: T, | ||||
|         exists: bool, | ||||
|     }; | ||||
| } | ||||
|  | ||||
| const Person = struct { | ||||
|     name: []const u8, | ||||
| }; | ||||
|  | ||||
| const Horse = struct { | ||||
|     canRide: bool = false, | ||||
|     rider: ?*const Person = null, | ||||
| }; | ||||
|  | ||||
| const Duck = struct { | ||||
|     friend: ?*Animal = null, | ||||
|     gone: bool = false, | ||||
| }; | ||||
|  | ||||
| const AnimalType = enum { | ||||
|     Horse, | ||||
|     Duck, | ||||
|     Person, | ||||
| }; | ||||
|  | ||||
| const Animal = union(AnimalType) { | ||||
|     Horse: Horse, | ||||
|     Duck: Duck, | ||||
|     Person: Person, | ||||
| }; | ||||
|  | ||||
| pub fn main() !void { | ||||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
|     const alloc = gpa.allocator(); | ||||
|     defer _ = gpa.deinit(); | ||||
|  | ||||
|     var list = std.ArrayList(i32).init(alloc); | ||||
|     defer list.deinit(); | ||||
|     try list.append(324); | ||||
|     try list.append(456); | ||||
|  | ||||
|     for (list.items) |item| { | ||||
|         std.log.debug("item: {}", .{item}); | ||||
|     } | ||||
|  | ||||
|     var animal = Animal{ .Horse = .{ .canRide = true } }; | ||||
|  | ||||
|     const person = Person{ .name = "Dragutin" }; | ||||
|  | ||||
|     if (animal == .Horse) { | ||||
|         animal.Horse.rider = &person; | ||||
|     } | ||||
|  | ||||
|     switch (animal) { | ||||
|         .Horse => |*horse| horse.rider = &person, | ||||
|         else => {}, | ||||
|     } | ||||
|  | ||||
|     var personAnimal = Animal{ .Person = .{ .name = "Aleksa" } }; | ||||
|  | ||||
|     var duck = Duck{ .friend = &personAnimal }; | ||||
|  | ||||
|     duck.gone = true; | ||||
|  | ||||
|     std.log.debug("Rider name: {s}", .{if (animal.Horse.rider) |rider| rider.name else "none"}); | ||||
|  | ||||
|     { | ||||
|         std.log.info("Ring buffer!", .{}); | ||||
|  | ||||
|         var rbuff = try WRB(i32).initCapacity(alloc, 32); | ||||
|         defer rbuff.deinit(); | ||||
|  | ||||
|         if (rbuff.isEmpty()) | ||||
|             try rbuff.pushBack(14); | ||||
|  | ||||
|         try rbuff.pushBack(16); | ||||
|         try rbuff.pushBack(2); | ||||
|  | ||||
|         const front = rbuff.frontPtr(); | ||||
|         front.* = 333; | ||||
|  | ||||
|         var iter = rbuff.iter(); | ||||
|  | ||||
|         while (iter.next()) |*value| { | ||||
|             std.log.info("rbuff value: {}", .{value}); | ||||
|         } | ||||
|  | ||||
|         std.log.info("the end!", .{}); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/other.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/other.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| const main = @import("main.zig"); | ||||
|  | ||||
| pub const pi = 3.14; | ||||
|  | ||||
| pub fn add() i32 { | ||||
|     try main.main(); | ||||
|  | ||||
|     return 3; | ||||
| } | ||||
							
								
								
									
										375
									
								
								talk.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								talk.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,375 @@ | ||||
| ## Intro | ||||
|  | ||||
| Before we start: | ||||
| - might be running slow - streaming + old laptop | ||||
| - no slides, just text | ||||
| - live coding demo | ||||
| - will try to cover most cool things | ||||
|     - but no multithreading/async/atomics and C interop details in talk | ||||
|  | ||||
| Who am I?: | ||||
| - Ivan Notaroš - nothke | ||||
| - indie gamedev for 10+ years | ||||
| - studied architecture | ||||
| - started by modding - 3D modeling | ||||
| - Unity, C# since ~2013 | ||||
| - many game jams: https://nothke.itch.io/ | ||||
| - Unity had too many limitations, esp for procgen, progressively went lower level | ||||
| - custom engine in C++ since 2020 | ||||
|     - making a rally game: Shakedown Rally in it | ||||
| - heard of Zig a few years ago | ||||
|     - kept hearing of cooler and cooler features | ||||
|     - started making an engine just to see how easy it would be to move C++ to Zig | ||||
| - I stream gamedev on twitch too: https://twitch.tv/nothke | ||||
| - Windows user all my life 😢 | ||||
|  | ||||
| ## Zig | ||||
| - Hard to put in an elevator pitch | ||||
| - Fell in love with language and community - https://ziglang.org | ||||
| - Don't know where to start, I'll try my best | ||||
|  | ||||
| Zig (language) facts: | ||||
| - Zig is an imperative, | ||||
| - structured, | ||||
| - general-purpose, | ||||
| - statically typed, | ||||
| - compiled, | ||||
| - system programming language | ||||
|  | ||||
| History: | ||||
| - designed by Andrew Kelley | ||||
|     - https://andrewkelley.me | ||||
| - first version (0.1) since 2016 | ||||
| - currently at 0.14 dev, 0.13.0 stable | ||||
| - since 0.10 - self-hosted | ||||
| - since 2020, Zig software foundation: https://ziglang.org/news/announcing-zig-software-foundation/ | ||||
|  | ||||
| Goals: | ||||
| - "better C" | ||||
| - simple, clear, readable | ||||
| - very explicit | ||||
| - maintainable | ||||
| - robust | ||||
| - sane defaults | ||||
| - fast: runtime AND compile | ||||
| - no hidden allocations | ||||
| - write all in Zig | ||||
| - minimal dependencies | ||||
| - no UB in debug or safe | ||||
| - unambigous, context-free syntax | ||||
| - one obvious way to do things | ||||
|  | ||||
| Some really cool bits (apart from already mentioned): | ||||
| - all-in-one cross-compiling toolchain | ||||
| - include and seamlessly interoperate with C code | ||||
| - comptime - powerful metaprogramming - written in zig | ||||
| - integrated build system - written in zig | ||||
| - no hidden allocations - easy to reason about memory | ||||
| - amazing standard library | ||||
|     - which is completely comprehensible! (unlike C++ STL 😛) | ||||
| - decentralized package manager | ||||
| - zls | ||||
| - pointer disambiguation | ||||
| - no exceptions - error types | ||||
| - no header files (!!!) | ||||
| - bit-packing types | ||||
| - SIMD vectors | ||||
| - no function or operator overloads | ||||
| - strong formatting convention | ||||
| - OOP-lite | ||||
| - no macros | ||||
| - if it looks like a function, its a function. Fields are just fields! | ||||
|  | ||||
| ### The toolchain | ||||
| - all-in-one | ||||
| - cross compile from-to any system | ||||
| - compile C and C++ | ||||
| - include C code | ||||
|     - translate-c - C to zig | ||||
|     - -ofmt=c - zig to C | ||||
| - very fast | ||||
| - build system written in Zig | ||||
|     - just `zig build run` | ||||
|     - no CMake! | ||||
| - integrated tests | ||||
| - 4 compiler modes `--release=[mode]` : | ||||
|     - debug | ||||
|     - safe | ||||
|     - fast | ||||
|     - small | ||||
| - lazy compiler | ||||
|     - only compiles what you use | ||||
|  | ||||
| ## Live demo! | ||||
|  | ||||
| ### installing | ||||
| - with VSCode: | ||||
|     - install Zig extension | ||||
|     - ctrl+shift+P | ||||
|         - install zig | ||||
|         - install zls | ||||
| - alternatively: | ||||
|     - with zvm https://www.zvm.app/ | ||||
|         - `zvm i --zls master` or `0.13.0` (for now) | ||||
|     - install binary | ||||
|         - build zls | ||||
|     - sudo apt install zig | ||||
|  | ||||
| ### Language walkthrough | ||||
|  | ||||
| const and var | ||||
| - `: T =` | ||||
| - initialization | ||||
| - `const` - immutable | ||||
|     - const resolved at compile time if it can be | ||||
|     - can act as an alias to types | ||||
| - `var` - mutable | ||||
|  | ||||
| integers | ||||
| - unsigned: `u8`, `u16`, `u32`.. | ||||
| - signed: `i8`, `u16`, `u32`.. | ||||
| - but also arbitrary width: `i2`, `u6`, `i31`.. | ||||
| - casting - peer type resolution | ||||
|     - narrow to wide - allowed | ||||
|     - wide to narrow - disallowed, must be explicit @intCast | ||||
|         - if compile-time known - casting checked at compile time | ||||
| - overflow is an error | ||||
|     - but explicit overflow operator `+%`, `-%` | ||||
| - Note: `const a = 1;` is a `comptime_int` | ||||
|  | ||||
| - floats `f16`, `f32`, `f64`, `f128` and `f80` | ||||
|  | ||||
| pointers (single item): | ||||
| - `*T` | ||||
| - `&` - address of operator | ||||
| - can't be null | ||||
| - (..we'll come back to more pointers..) | ||||
|  | ||||
| `[N]T` - arrays | ||||
| - on stack, compile-time known size | ||||
|     - size part of type | ||||
| - `[3]T` | ||||
| - `[_]T` - inferred size from initialization | ||||
| - unambiguously values | ||||
|     - unlike C which pretend to be pointers | ||||
|  | ||||
| `[]T` - slices | ||||
| - `const slice: []T = &arr;` | ||||
| - or `const slice = arr[0..];` | ||||
|  | ||||
| strings | ||||
| - what strings..? They're just `[]u8` | ||||
| - "string class" not needed, `std.mem.-` functions are rich enough for every need | ||||
| - For unicode there's `std.unicode.-` | ||||
|  | ||||
| `++` `**` - compile-time array operators | ||||
| - `arr ++ arr2` - concatenates | ||||
| - `arr ** 3` - repeats | ||||
|  | ||||
| structs | ||||
| - `const MyStruct = struct {}` | ||||
| - fields | ||||
|     - always public | ||||
|     - rearranged to better fit memory | ||||
|         - unless `extern` | ||||
|     - can be default initialized | ||||
| - are namespaces | ||||
| - namespaced functions | ||||
|     - if first parameter is `MyStruct`, acts as a "method" | ||||
|     - if self needs to mutate, pass as pointer `self: *MyStruct` | ||||
| - initialization | ||||
|     - uninitialized fields not allowed | ||||
|         - (but fields can be default initialized ^) | ||||
|     - force uninitialized with `= undefined` | ||||
|         - explicitely shoot yourself in the foot! (unlike C) | ||||
| - files are structs too! | ||||
| - `packed` | ||||
|     - bools become 1 bits | ||||
|     - arbitrary-sized ints become bit-sized | ||||
| - no ctors/dtors - more on that later.. | ||||
|  | ||||
| enums and unions | ||||
| - enums | ||||
| - (bare) unions | ||||
|     - known which type | ||||
|     - no type punning | ||||
| - tagged unions | ||||
|     - use a backing enum | ||||
|     - switch | ||||
|     - polymorphism on stack! | ||||
| - ^ enums and unions also act as namespaces that can have functions! 😉 | ||||
|  | ||||
| Zig has no operator overloads! | ||||
| - = is always a (shallow) copy | ||||
| - [] only works on arrays, slices and multi-item pointers | ||||
| - & always a pointer to - looking at C++ | ||||
|  | ||||
| But I'm a gamedev and really need my vector arithmetic overloads 😭 | ||||
| - Don't worry! There are built-in Vectors! 😍 | ||||
|  | ||||
| `@Vector(3, i32)` | ||||
| - SIMD out of the box | ||||
| - can index | ||||
| - cannot loop through | ||||
|     - but can cast into compatible array `[3]f32 = @Vector(3, f32)` | ||||
|  | ||||
| functions | ||||
| - `fn` | ||||
| - parameters always const | ||||
|     - compiler can infer copy or const-ref, depending on size | ||||
|     - params | ||||
| - return must be known | ||||
|     - but comptime expressions possible | ||||
| - function pointers | ||||
|  | ||||
| control flow | ||||
| - `if (bool)` | ||||
| - `while (bool)` | ||||
| - `for (array) |x| {}` | ||||
|     - `|x|` capture bars | ||||
|         - expression creates variable | ||||
|     - range `0..` | ||||
|     - multi-item | ||||
|     - inline - unrolls loops | ||||
| - switch | ||||
|     - exhaustive | ||||
|  | ||||
| !? | ||||
| - `!T` errors and `?T` optionals | ||||
| - ! error unions | ||||
|     - error enum | ||||
|     - type example: divide by zero | ||||
|     - handling errors: | ||||
|         - try | ||||
|         - catch | ||||
|         - switch | ||||
| - ? optionals | ||||
|     - can be `null` | ||||
|     - `?*T` - nullable pointers | ||||
|         - don't consume extra space | ||||
|     - `opt.?` unwraps value, if null throws error | ||||
|     - `opt orelse 0` if null use another value | ||||
|     - `if (opt) |value| {}` if not null, unwraps | ||||
|     - `while (opt) |value| {}` runs until null | ||||
|         - can be used to implement iterators `while (iter.next()) ..` | ||||
|  | ||||
| ### Disambiguation of Pointers | ||||
| - in C/C++, a pointer can be | ||||
|     - dereferenced `*ptr` | ||||
|     - indexed `ptr[3]` - and not bounds checked | ||||
|     - added to `ptr + 1` | ||||
|     - `nullptr` | ||||
|     - not known if it points to a null terminated string..? 🤷♂️ | ||||
|  | ||||
| - Zig disambiguates all these and puts them in separate types: | ||||
|     - `*T` - single-item pointer - cannot be indexed | ||||
|     - `[]T` - slice - bounded, cannot be dereferenced with t.* | ||||
|     - `[*]T` - multi-item pointer - unbounded | ||||
|     - `[:0]` - sentinel-terminated, 0 in this case | ||||
|     - `?*T` `?[]T` - nullable | ||||
|     - `*anyopaque` - equivalent to void* | ||||
|     - `*align(1:0:1) T` - pointers can also hold alignment and bit offset in their type | ||||
|     - `[*c]` - can do all - but use it only for interoperating with C code! | ||||
|      | ||||
| - Why? intent is much clearer! | ||||
|  | ||||
| ### Comptime | ||||
| - no macros, no templates, no constexpr | ||||
| - call any function at compile time! | ||||
| - types are types | ||||
|     - (at compile time only) | ||||
|     - can be used to return types to create generics | ||||
|         - example: Optional(T) | ||||
| - full static reflection | ||||
|     - e.g. looping through fields | ||||
|         - https://gist.github.com/travisstaloch/71a7a2bc260997abe06016c619b40bf2 | ||||
| - `anytype` | ||||
|     - function parameter type that can ONLY be inferred at compile-time | ||||
|     - similar to template function `auto` parameters in C++ | ||||
| - `comptime var` | ||||
|     - can be mutated but only at compile-time | ||||
|     - acts as const at runtime | ||||
|  | ||||
| ## Memory Management | ||||
|  | ||||
| Memory management in other languages: | ||||
| - manual (C) - malloc() free() | ||||
| - RAII (C++) | ||||
| - GC (Java/C#/python/Go) | ||||
| - compile time resolved (rust) | ||||
|  | ||||
| Zig - manual, BUT, unlike C: | ||||
| - `defer` | ||||
|     - executes at the end of the scope | ||||
|     - like RAII - BUT controlled by the user | ||||
|     - `errdefer` like defer but only when error is thrown | ||||
| - has allocators | ||||
|  | ||||
| ### Allocators | ||||
| - interface used in std with anything that allocates heap memory | ||||
| - PageAllocator  | ||||
|     - the "dumb" one | ||||
|     - makes syscalls | ||||
| - FixedBufferAllocator | ||||
|     - provide a buffer, can be on stack | ||||
|     - not resizeable | ||||
| - GeneralPurposeAllocator | ||||
|     - can catch leaks in debug | ||||
| - ArenaAllocator | ||||
|     - can discard entire chunks | ||||
| - TestingAllocator | ||||
|     - only available in tests | ||||
|  | ||||
| - Demo how to use with `std.ArrayList` | ||||
|  | ||||
| ## Built-in Tests | ||||
| - `test "My Test" {}` | ||||
| - `std.testing.expect-` | ||||
| - just `zig build test` | ||||
|  | ||||
| ## Package manager | ||||
| - build.zig.zon | ||||
| - not centralized | ||||
| - hash to check code correctness | ||||
| - `zig fetch --save "link"` | ||||
|  | ||||
| ## Cons | ||||
| - not 1.0 yet | ||||
|     - changes from version to version | ||||
|     - async not there yet | ||||
| - C/C++ ecosystem is much older and versatile | ||||
| - no built-in vtable-inheritance (dynamic dispatch) | ||||
|     - but you can do your own in comptime | ||||
|     - example (old): https://github.com/alexnask/interface.zig | ||||
| - no lambdas | ||||
|     - but https://github.com/ziglang/zig/issues/6965 | ||||
|  | ||||
| ## Community and Resources | ||||
| - Online: | ||||
|     - discord: https://discord.gg/invite/zig | ||||
|     - ziggit: https://ziggit.dev/ | ||||
|     - Dude the Builder: https://www.youtube.com/@dudethebuilder/videos | ||||
| - Offline: | ||||
|     - Software you can love https://sycl.it/ | ||||
|     - meetups on zig | ||||
|  | ||||
| ## Future of Zig | ||||
| - goal of 0.14.0: super fast compile times | ||||
| - getting rid of LLVM: | ||||
|     - with LLVM 170MB, without 4.4 | ||||
|  | ||||
| ## Conclusions | ||||
| - wHeRe dOeS zIg fIt iN tHe mOdeRn wOrLd?? | ||||
|     - Aren't you convinced by the talk..? | ||||
|     - Reduces friction | ||||
| - Companies already using Zig: | ||||
|     - Tigerbeetle https://tigerbeetle.com/ | ||||
|     - Bun https://bun.sh/ | ||||
|     - Uber (build system) | ||||
| - `zig zen` | ||||
| - What about Odin, jai..? | ||||
| - Will do the same talk in Hamburg for code.talks | ||||
|  | ||||
| Epilogue: | ||||
| - Thanks! Now you can code in Zig⚡ ! | ||||
| - nothke: https://nothke.github.io/ | ||||
		Reference in New Issue
	
	Block a user