The compiler currently errors when the .decls slice is non-empty.
More context at https://github.com/ziglang/zig/issues/383.
One (imho strong) argument to allow this is that we can make really convenient interface implementations:
// Definition of an interface:
const Allocator = std.meta.Interface(struct {
pub const Error = error{OutOfMemory};
alloc: fn (self: *std.meta.Self, len: usize) Error![]u8,
free: fn(self: *std.meta.Self, ptr: []u8) void,
});
// Usage is just taking the interface type, it's a "fat pointer":
fn process(allocator: Allocator, items: []const u8) !void {
// Just call functions on the interface like on normal objects.
// this is provided via created functions from .decls
const buf = try allocator.alloc(items.len);
defer allocator.free(buf);
…
}
// Implementing interfaces is still duck typing:
const FixedBufferAllocator = struct {
const Self = @This();
buffer: []u8,
allocated: bool = false,
pub fn init(buf: []u8) Self {
return Self { .buffer = buf };
}
// access public symbols of the struct we pass to std.meta.Interface
// as we can usingnamespace them
pub fn alloc(self: *Self, size: usize) Allocator.Error!void {
if(self.allocated)
return error.OutOfMemory;
if(size > self.buffer.len)
return error.OutOfMemory;
self.allocated = true;
return self.buffer[0..size];
}
pub fn free(self: *Self, ptr: []u8) void {
std.debug.assert(ptr.ptr == self.buffer.ptr);
self.allocated = false;
}
};
fn main() !void {
var fba = FixedBufferAllocator.init(&some_array);
// Interface().get(ptr) will duck-type match the interface into a fat pointer
try process(Allocator.get(&fba), "Hello, Zig");
}
To make the convenient function calls like allocator.free(…) we need TypeInfo.Struct.decls.
The neat thing is: The example code above does feel native, like if interfaces would be a part of the language. But they are just a clever use of comptime. This would kinda also close #130 as "implemented"
A minor usecase - when translate-c can't handle something I make a wrapper function instead:
[nix-shell:~/bluetron/blinky]$ cat wrapper.c
#include "stdbool.h"
#include "stdint.h"
#include "nrf_delay.h"
#include "boards.h"
void bluetron_nrf_delay_ms(uint32_t ms_time)
{
nrf_delay_ms(ms_time);
}
It would be nice to be able to wrap my @cImport to automatically rename bluetron_foo to foo, replacing the original declaration.
This is kind of similar to --wrap=foo in ld.
Most helpful comment
One (imho strong) argument to allow this is that we can make really convenient interface implementations:
To make the convenient function calls like
allocator.free(…)we needTypeInfo.Struct.decls.The neat thing is: The example code above does feel native, like if interfaces would be a part of the language. But they are just a clever use of
comptime. This would kinda also close #130 as "implemented"