#comptime_int, arrays, and many-item pointers

1 messages · Page 1 of 1 (latest)

rotund elm
#

Given an array type like [n]u8 where n is a constant (comptime_int), is there some way to specify a concrete type of [*]u8?

Stated another way: Can I abstract over arrays of a known size and many-item pointers?

I'm asking because I have some code that is currently generic over array size, but most of the methods on that type don't actually care about the array's length and it would be convenient to instantiate the generic type with n = *.

Thanks!

coarse rapids
#

well, not really in the parameter definition

#

but there is a way to do this

#
fn foo(array: anytype) void {
    comptime assert(@TypeOf(array) == [array.len]u8);
}
#

that, or you could just use a slice

#

as in, []const u8 or whatever else

#

you can coerce *const [n]u8 to []const u8 implicitly

rotund elm
#

re slices: i'm doing that one-level higher in my system. i was (perhaps being lazy) trying to avoid refactoring some code

#

reading your code example, trying to understand

coarse rapids
#

essentially, it takes a parameter of anytype

#

that means you could technically do foo(3) and there's no type mismatch by itself

#

but then that may be a compile error depending on how you treat the array parameter

#

e.g. 3[0] doesn't make sense, so compile error

#

basically, ducktyping

#

luckily, in zig, type reflection is very easy

#

so you can do @TypeOf(array), which would return the type of the parameter in that instantiation

#

if you passed 3, that would be comptime_int, which != [array.len]u8

#

though, there's also the fact that 3.len doesn't make sense

#

so that would probably error out first

#

but if you were to accidentally pass [3]u16, then it would compare [3]u16 == [3]u8, which would return false, and trigger an assertion failure at comptime

#

make sense?

rotund elm
#

that makes sense, but i'm not sure it addresses my question, so i'm trying to articulate it better

#

so if I understand correctly, std.builtin.Type is the representation for anytype. I'd like to abstract over two different enum cases: .Pointer with .size = .Many and .Array with .len = ....

#

Now that I'm saying that, I think I know how to do it:

coarse rapids
#

(pedantic note: std.builtin.Type is not the representation for anytype, the former is just a builtin struct returned by @typeInfo that describes information about a type, and the latter is a syntax for designating parameters whose type is determined and monomorphized at the callsite)

rotund elm
#

oh, so anytype is actually an AST/IR instead of that reflection struct?

coarse rapids
#

yeah, essentially

#

it's just that you can do @TypeOf(value) to get the specific type it's monomorphized to in the function body

#

and then subsequently get the @typeInfo of that type

rotund elm
#

got it

#
const std = @import("std");

const SizeTag = enum {
  unknown,
  known,
};

const Size = union(SizeTag) {
  unknown: struct{},
  known: comptime_int,
};

pub fn Thing(comptime size: Size) type {
  switch (size) {
     .unknown => return [*]u8,
     .known => |n| return [n]u8,
  }
}

pub fn main() void {
  std.debug.print("{any}\n", .{ Thing(Size{ .unknown = .{} }) });
  std.debug.print("{any}\n", .{ Thing(Size{ .known = 4 }) });
}
#

^ that does what i want

#

it's a bit more verbose than i'd have liked, but it makes sense. the lisper in me was trying to abstract over the [...]... syntax

#

Thanks for helping me look at this differently and for the info on how anytype works. Really enjoying my time with Zig!

coarse rapids
#

happy to have another cheerful soul aboard

coarse rapids
#
fn Thing(comptime size: ?comptime_int) type {
    return if (size) |n|
        [n]u8
    else
        [*]u8,
}
#

also, be wary: [*]u8 and [n]u8, although of similar syntax, are quite distinct in their semantics

rotund elm
#

haha of course, that makes much more sense

coarse rapids
#

array types are value types in zig, meaning when you do var b = a;, it makes a copy of the array, not a reference

rotund elm
#

yeah, i realize that this is probably an ill-advised thing to abstract over.

#

i was avoiding a bigger refactor, but of course i have to do that refactor anyway 🙂

#

and then curiosity got the better of me

coarse rapids
#

lol, I sympathise with that

#

one moment I'm writing opengl, the next I'm parsing XML and re-reading the standard

rotund elm
#

well mercifully, i've been able to actually build things with zig... every time i try rust, i'm like 50 crates and 10 RFCs deep before i realize that i don't even remember what i was doing

coarse rapids
#

amen