It appears in zig we are able to define function types as properties of structs. I am wondering how to use struct values to create the function response.
In the following code:
const std = @import("std");
pub fn main() !void {
const t = Animal{
.name = "My Name",
.age = 5,
.talk = *const fn () [_]u8 {return .{.name}},
.doubleAge = *const fn () i32 {return 2 * .{.age}},
};
std.log.info("{s}", .{t.talk()});
std.log.info("{}", .{t.doubleAge()});
}
const Animal = struct {
name: []u8,
age: i32,
talk: fn () []u8,
doubleAge: fn () i32,
};
The .talk function has a compiler error for “not being able to determine array size”
The .doubleAge function has a compiler error for “not being able to instantiate array”
0
Zig does not have closures. If you want to access the struct, you will need to pass it as a parameter to the function:
const std = @import("std");
pub fn main() !void {
const t = Animal{
.age = 5,
.doubleAge = doubleAge,
// or you can use some other approach to declare the function locally,
// for example:
// .doubleAge = (struct {
// fn _(self: Animal) i32 {
// return 2 * self.age;
// }
// })._,
};
std.log.info("{}", .{ t.doubleAge(t) }); // prints: 10
}
const Animal = struct {
age: i32,
doubleAge: fn (Animal) i32,
};
fn doubleAge(self: Animal) i32 {
return 2 * self.age;
}
Note, that these aren’t function pointers, but function bodies, which only exist at compile time. If you do std.log.info("{}", .{ @sizeOf(Animal) });
, it will print 4
(for a single i32
). As I understand it, this only creates an association between a particular function and an instance of the struct at compile time:
const std = @import("std");
pub fn main() !void {
const foo = Animal{
.age = 1,
.doubleAge = (struct {
fn _(self: Animal) i32 {
return 2 * self.age;
}
})._,
};
const bar = Animal{
.age = 1,
.doubleAge = (struct {
fn _(self: Animal) i32 {
// actually triple
return 3 * self.age;
}
})._,
};
std.log.info("{}", .{ foo.doubleAge(foo) }); // prints: 2
std.log.info("{}", .{ bar.doubleAge(bar) }); // prints: 3
std.log.info("{}", .{ foo.doubleAge(bar) }); // prints: 2
std.log.info("{}", .{ bar.doubleAge(foo) }); // prints: 3
}
const Animal = struct {
age: i32,
doubleAge: fn (Animal) i32,
};
.name = "My Name", .talk = *const fn () [_]u8 {return .{.name}}, .doubleAge = *const fn () i32 {return 2 * .{.age}},
This syntax is completely wrong:
- String literals are immutable/const in Zig, but you declared name as a slice of mutable bytes. This won’t compile.
- A function cannot be declared like this, it has to be in a struct (a file is a struct too).
- In the struct you declare a function body (
fn () ...
), but here you’re trying to declare a function pointer (*const fn () ...
). - In the struct you use a slice (
[]u8
), but here you’re attempting to use array literal syntax ([_]u8
). .{.name}
and.{.age}
– make no sense.
3