You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
conststd=@import("std");
constprint=std.debug.print;
// my String typeconstString: type= []constu8;
// function returning a typefnisString() type {
returnString;
}
test"What?" {
// a String literal is a const pointer to an array of charactersconstelixir="Elixir";
print("\nThe variable with value {s} is a string literal. Check the type: {}\n", .{ elixir, @TypeOf(elixir) });
varzig: String="Zig";
zig="zig"std.debug.print("\nThe variable with value {s} is a String: {}\n", .{ zig, @TypeOf(zig) ==isString() });
constptr_elixir=&elixir;
constptr_zig=&zig;
print("\n{}\t {}\t {s}\n", .{ @TypeOf(ptr_elixir), @TypeOf(ptr_elixir.*), ptr_elixir.* });
print("\n{}\t {s}\n", .{ @TypeOf(ptr_zig.*), ptr_zig.* });
trystd.testing.expect(@TypeOf(l) ==isString());
constword= [5]u8{ 'h', 'e', 'l', 'l', 'o' };
constslice_word=word[0..];
print("\nArrays: {s}\t {}\t {s}\t {}\n", .{ word, @TypeOf(word), slice_word, @TypeOf(slice_word) });
}
Run zig test my_file.zig:
The variable with value Elixir is a string literal. Check the type: *const [6:0]u8
The variable with value zig is a String? : true
*const [6:0]u8 Elixir
^^ the pointer is pointing to a const pointer pointing to an array of characters (1 byte, 8 bites)
*[]const u8 []const u8 Zig
# ^^ if we use "const zig = "Zig", then we get @TypeOf(&zig) == *const []const u8
# the type determines the presence of the first "const"
Arrays: hello [5]u8 hello *const [4]u8
All 1 tests passed.
Lets summarise
Arrays are [n]T of comptime known length. You can instantiate them:
const word = [5]u8{'h', 'e', 'l', 'l', 'o'} with type [5:0]u8
Slices are []T of types T with runtime known length. They are made of a pointer to the first element of an Array and a length.
For example, when you allocate memory for n elements of type T, we get a slice: var slice_of_t: []T = allocator.alloc(T, n).
You can instantiate a slice from an array: we check that we get a pointer
const slice_word = word[0..] with type *const [4]u8
Recall that the type of a string literal is a pointer to an array.
❗ printIt is expecting a slice, []const u8, which is a pointer....
"zig" has type *const [3:0]u8, a pointer, ✅
since testIt() returns an [5]u8, an array, we need to pass &testIt() ✅
Now, can we mutate a literal string? Yes, dereference it!
❗ We need to use a pointer to pass the struct Person to the function "increase".
Indeed, the arguments of a function are immutable, so inside the function, we can't modify the p we get.
=> we get: "error: cannot assign to constant"
When we pass a pointer, the pointer is not modified inside the function. However, we can mutate the data at which the pointer is pointing at. We don't need to deference the pointer: p.salary works fine.
Now consider a struct that holds internal methods. Again, when the method modifies one of the fields of the struct, you must use a pointer. Note that the inner method uses a reflection.
conststd=@import("std");
// the input is a pointer to CONSTANT values; this is validfnsum(input: []constu8) u8 {
varsum: u8=0;
for (input) |e|sum+=e;
returnsum;
}
// we add the index to each element of the array// the argument is a MUTABLE slicefnmut(input: []u8) []u8 {
// this is not possible: "error: cannot assign to constant"// for (input, 0..) |e: u8, i: usize| {// e += i;// }// instead, this is validfor (input, 0..) |_, i: usize| {
input[i] +=1;
}
// alternativefor (input, 0..) |*v: **u8, i: usize| {
v.*+=i;
}
returninput;
}
test"arrays" {
constcst_input= [_]u8{ 1, 2, 3, 4, 5 };
constsum=sum1(&cst_input);
trystd.testing.expectEqual(sum, 15);
// we define a mutable array.varvar_input= [_]u8{ 1, 2, 3, 4, 5 };
// const mutInput = mut(&cst_input); <- this failsconstmutInput=mut(&var_input);
trystd.testing.expectEqualSlices(u8, mutInput, &[_]u8{ 2, 3, 4, 5, 6 });
}
This is similar to when you want to mutate data via its pointer (more involved, yes...)
// mutate via the pointerfndb_ptr(x: *u8) void {
x.**=2;
}
// just return another valuefndb(x: u8) u8 {
returnx*2;
}
test"mut" {
varx: u8=1;
db_ptr(&x);
trystd.testing.expectEqual(x, 2);
vary: u8=1;
y=db(y);
trystd.testing.expectEqual(y, 2);
}
https://zig.news/ is a good place to search on ziggy problems.
Explore types with
@TypeOf
[building...]
Vademecum
Run
zig test my_file.zig
:Lets summarise
[n]T
of comptime known length. You can instantiate them:const word = [5]u8{'h', 'e', 'l', 'l', 'o'}
with type[5:0]u8
[]T
of typesT
with runtime known length. They are made of a pointer to the first element of an Array and a length.const slice_word = word[0..]
with type*const [4]u8
const zig = "zig"
has type*const [3:0]u8
Ok, now we test our understanding:
We can use it like this:
Now, can we mutate a literal string? Yes, dereference it!
gives:
Structs
Now consider using a struct. Pointers are needed here when you use functions to modify.
We get:
Now consider a struct that holds internal methods. Again, when the method modifies one of the fields of the struct, you must use a pointer. Note that the inner method uses a reflection.
We get as expected:
Pause
Check this video:
WFT Comptime....
❗ References to keep!
A first link:
Then, a GitHub link:
The text was updated successfully, but these errors were encountered: