Initial
This commit is contained in:
commit
64be90de80
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/
|
Loading…
Reference in New Issue
Block a user