while (try iter.next()) |entity| {
const t = struct {
fn callback(item: []const u8) bool {
return strings.contains(item, entity.path);
}
};
if (self.option.ignore_dirs != null and strings.some(self.option.ignore_dirs.?, t.callback)) {
continue;
}
if (entity.kind == .file) {
std.debug.print("entity file = {s}\n", .{entity.path});
} else {
std.debug.print("entity dir = {s}\n", .{entity.path});
}
}
#How can I capture external variables and use closure functions?
1 messages · Page 1 of 1 (latest)
there are no closures in zig, you have to model them explicitly yourself. for example by using structs with the data and a function that also takes self
Can you provide a simple example? Thank you.
sorry not right now, its 3am here soon and I'm going to sleep
I'm sorry for bothering you. I don't know your working hours, but I hope you can get some rest soon. Thank you.
no problem at all, I'll post a quick example tomorrow if I haven't forgotten it by then
actually whatever this is what I was thinking of ```rust
const Callback = struct {
my_data: Whatever,
another_field: Foo,
pub fn call(self: Self, normal_args: ...) ... { ... }
}
which also means this has to be supported by the interface that accepts the callback, if it expects a simple function pointer without any extra state you can't have any extra state (other than using global state of course)
another option is for the function to take separate callback and context arguments, where the context is then also passed to the callback. you can find both variants in std.sort
What people usually do to emulate stack capturing macros is
fn calling_fun(callback: anytype) void {
callback.call(...);
}
calling_fun((struct{
x: T,
pub fn call(self: @This) V {
...
}
}){.x = local})
Or at least that's what I've seen
What you want to capture, you put inside the struct as member variables
real examples of this pattern are std.sort.*Context functions
This creates a circular dependency problem for me.
Given
const ItemManagerInterface = struct {
interact: *fn(mgr: *T) void,
};
pub const Item = struct {
// ...
pub fn do_something(self: *Item, iface: *ItemManagerInterface) void {
iface.interact();
}
};
pub const ItemManager = struct {
iface: ItemManagerInterface,
items: std:ArrayList(*Item),
// ...
pub fn init() ItemManager {
var ret = .{
.iface = {
// ... what should be here?
},
.items = std.ArrayList(*Item).init(gpa),
}
return ret;
}
pub fn update(self: *ItemManager) void {
for (self.items.items) |itm| {
itm.do_something(&self.iface);
}
}
pub fn interact(self: *T) {
/// ...
}
};
Note: it's *const fn, not *fn. The latter would only work at comptime, if at all
maybe. But key problem is chicken-egg.
Item have to declare pointer to ItemManger and vice versa.
I don't actually see what the issue is, you've omitted too much code and provided no error message
There is an Item which depends on ItemManagerInterface but ItemManagerInterface is unable to reference ItemManager because it is not declared yet
in C this could be resolved with forward declaration struct ItemManager; how to do it in zig?
not sure what you mean, you can reference it
at namespace level, declarations are order-independent
you just can't value value-recursive types
but they could be in different files because there are many sort of Items which packed into tagged union
okay? they can still reference each other
please open a thread with your specific problem, alongside what you're actually trying to do
Just closure would be one of ways but ok