Created
October 23, 2022 14:11
-
-
Save rapando/eff56ef975829b77cedb869ced1b53ca to your computer and use it in GitHub Desktop.
Zig Learning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const eq1 = std.mem.eql; | |
const ArrayList = std.ArrayList; | |
const test_allocator = std.testing.allocator; | |
// struct definition | |
const Person = struct { | |
x: f64, | |
y: f64, | |
}; | |
// struct elements can have default values, | |
// structs can also be anonymous | |
const Coordinates = struct { | |
x: f64 = 34.00, | |
y: f64 = 0.50, | |
z: f64, // only z needs a value in declaring a new struct instance | |
fn print(self: *Coordinates) void { | |
std.debug.print("you are at ({},{},{})\n", .{ self.x, self.y, self.z }); | |
} | |
}; | |
// enums | |
const EnumType = enum { | |
One, | |
Two, | |
// Three = 3, // can't print this directly, has to be inferred | |
}; | |
// error handling | |
const MyError = error{ | |
GenericError, // just like enums | |
OtherError, | |
}; | |
// using meta programming, you can create structs that take in a specified data type | |
fn Vec2Of(comptime T: type) type { | |
return struct { x: T, y: T }; | |
} | |
const V2i64 = Vec2Of(i64); | |
const V2f64 = Vec2Of(f64); | |
// factory type for heap programming | |
const Gpa = std.heap.GeneralPurposeAllocator(.{}); | |
pub fn main() void { | |
std.debug.print("Hello, {s}!\n", .{"World"}); | |
const a: i32 = 5; | |
var b: u32 = 5000; | |
std.debug.print("a={d}, b={d}\n", .{ a, b }); | |
// for explicit type coercion, use @ | |
const inferred_constant = @as(i32, 5); | |
var inferred_variable = @as(u32, 5000); | |
std.debug.print("inferred_constant={d}, inferred_variable={d}\n", .{ inferred_constant, inferred_variable }); | |
// you must define variables with a value. if not, use 'undefined' | |
const c: i32 = undefined; | |
var d: u32 = undefined; | |
std.debug.print("c={d}, d={d}\n", .{ c, d }); | |
// arrays | |
var arr = [5]u8{ 'a', 'b', 'c', 'd', 'e' }; | |
std.debug.print("array={}\n", .{arr[0]}); | |
var arr_part: []u8 = arr[0..2]; | |
std.debug.print("arr_part length {}\n", .{arr_part.len}); | |
// std.debug.print("0..2 : {}\n\n", .{arr[0..2]}); | |
foo(); | |
std.debug.print("foo_int={}\n", .{foo_int()}); | |
// to ignore the output | |
_ = foo_int(); | |
func_with_params(a); | |
// structs | |
var person: Person = Person{ | |
.x = 90.9, | |
.y = 80.5, | |
}; | |
std.debug.print("person: {}\n", .{person}); | |
var kenya: Coordinates = Coordinates{ | |
.x = 0.56, | |
.z = 36, | |
}; | |
std.debug.print("co-ordinates: {}\n", .{kenya}); | |
kenya.print(); | |
// this is a tuple, basically an anonymous struct {1,2} | |
// that's what we've been using in the print statement | |
// ---- enums | |
std.debug.print("enumOne: {}\n", .{EnumType.One}); | |
std.debug.print("enumTwo: {}\n", .{EnumType.Two}); | |
// std.debug.print("enumThree: {}\n", .{@enumToInt(EnumType.Three) == 3}); | |
// --- control structures | |
var three: i32 = 2; | |
if (three == 3) { | |
std.debug.print("is three\n", .{}); | |
} else { | |
std.debug.print("is not three\n", .{}); | |
} | |
switch (three) { | |
0 => std.debug.print("is zero\n", .{}), | |
1 => std.debug.print("is two\n", .{}), | |
3 => std.debug.print("is three\n", .{}), | |
else => std.debug.print("is other\n", .{}), | |
} | |
// zig provides a for loop that only works on arrays and slices | |
var array = [_]i32{ 47, 48, 49 }; | |
for (array) |value| { | |
std.debug.print("array: {}\n", .{value}); | |
} | |
for (array) |value, index| { | |
std.debug.print("index:{}, value:{}\n", .{ index, value }); | |
} | |
// while loop | |
var index: u32 = 0; | |
while (index < 2) { | |
std.debug.print("value: {}\n", .{array[index]}); | |
index += 1; | |
} | |
// error handling | |
// catch traps and handles errors bubbling up | |
_ = error_handling(42) catch |err| { | |
std.debug.print("error : {}\n", .{err}); | |
}; | |
// pointers | |
var pointer_val: i32 = 90; | |
pointer_printer(&pointer_val); | |
// ------------- META PROGRAMMING | |
// types are valid values at compile time | |
// most runtime code will also work at compile time | |
// struct field evaluation at compile time duck-typed | |
// available tools for compile-type reflection | |
var meta_x: i64 = 47; | |
var meta_y: i32 = 47; | |
std.debug.print("i64-meta : {}\n", .{meta_programming(meta_x)}); | |
std.debug.print("i32-meta : {}\n", .{meta_programming(meta_y)}); | |
var v1 = V2i64{ .x = 47, .y = 47 }; | |
var v2 = V2f64{ .x = 47, .y = 47 }; | |
std.debug.print("v1={}\n v2={}\n\n", .{ v1, v2 }); | |
// // --------------- THE HEAP | |
// // zig gives you options to interact with the heap | |
// // they all follow the same pattern | |
// // 1. create an allocator factory struct | |
// // 2. retrieve the std.mem.Allocator struct | |
// // 3. use the alloc/free and create/destroy functions to manipulate the heap | |
// // 4. (optional) deinit the Allocator factory | |
// var gpa = Gpa{}; // instantiate the factory | |
// var galloc = &gpa.allocator; // retrieve the created allocator. | |
// // scope lifetime of the allocator to this function and perform cleanup | |
// defer _ = &gpa.deinit(); | |
// var slice = try galloc.alloc(i32, 2); | |
// // uncomment the following line to remove memory leak warning | |
// defer galloc.free(slice); | |
// var single = try galloc.create(i32); | |
// defer galloc.destroy(single); | |
// slice[0] = 47; | |
// slice[1] = 48; | |
// single.* = 49; | |
// std.debug.print("slice : [{},{}]\n", .{ slice[0], slice[1] }); | |
// std.debug.print("single: {}\n", .{single.*}); | |
} | |
pub fn foo() void { | |
std.debug.print("foo!\n", .{}); | |
} | |
pub fn foo_int() i32 { | |
return 47; | |
} | |
pub fn func_with_params(x: i32) void { | |
std.debug.print("func_with_params={}\n", .{x}); | |
} | |
// error handling | |
fn error_handling(v: i32) !i32 { | |
if (v == 42) return MyError.GenericError; | |
return v; | |
} | |
fn pointer_printer(value: *i32) void { | |
std.debug.print("pointer : {}\n", .{value}); | |
std.debug.print("value : {}\n", .{value.*}); | |
} | |
fn meta_programming(x: anytype) @TypeOf(x) { | |
// note that this if statement happens at compile time, not runtime. | |
if (@TypeOf(x) == i64) { | |
return x + 2; | |
} else { | |
return 2 * x; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment