Shortest syntax to declare an array of strings

Hi All, I’m very very new to Zig (Ruby/JS background and C for my hobby projects). After some searches it seems that the syntax to declare an array of strings is

var a3: [3][]const u8 = [_][]const u8{ "Hello", "Foo", "Bar" };
print("{s}", .{a3});

I’m quite surprised of a such verbosity compared to C

char* a3[] = { "Hello", "Foo", "Bar" };

Is there something I’m missing ?

1 Like

I believe you can do it like this with what’s known as a tuple literal in Zig:

var a3: [3][]const u8 = .{ "Hello", "Foo", "Bar" };

The tuple literal on the right hand side will be coerced into an array thanks to the explicit type info you provide on the left hand side.

1 Like

Thanks ! That’s far better !

Another question : why can’t I declare as
var a3: [_][]const u8 = .{ "Hello", "Foo", "Bar" };
I get this error : error: unable to infer array size

1 Like

The reason is that the [_] array size inference syntax is only allowed on an array literal per se. But I share your wonder at why the compiler can’t infer the size when it’s dealing with a compile time known literal value being coerced.

This works:

const std = @import("std");

test {
    const a3 = [_][]const u8{ "Hello", "Foo", "Bar" };
    std.debug.print("{s}\n", .{a3});
}
4 Likes

It might be because this var a3: [_][]const u8 = .{ "Hello", "Foo", "Bar" }; tries to assign anonymous struct, aka tuple, to an array variable. I often find that specifying the type in place of that dot at the literal initialization site MyType{} is better than after the colon : MyType =, whenever it can be done.

2 Likes

Hmmm… I’m totally lost here :wink:

What’s the difference between
var name: type = tuple
and
const name = type + array content
?
Do you have a web page link that explains this concept ?

For now, the only reference I’m aware of is Karl Seguin’s blog (added to Documentation - The Zig Programming Language).

EDIT : If I’m struging with basic concepts, it’s obvious that trying to understand comptime is a bad idea for now

I believe working your way through the langref gets you a pretty good grasp of the basics. The challenge is to start applying and expanding that knowledge by reasoning in practice about what the compiler does and doesn’t do, what it can and cannot do in specific cases.

In this specific case of initializing an array variable with a tuple while asking the compiler to infer the size of the resulting array, the compiler fails. It certainly seems like it should be possible to infer the size, so my guess was that the current rules of coercing tuples to arrays require you to specify the array size yourself, which in the end is probably a good thing, since it keeps from bloating the compiler with handling all of the special cases like this one and making it more complex (and eventually slower), plus, it forces you to be more conscious and explicit with the type coercion that’s happening in this particular case.

2 Likes

var declares a mutable variable while const declares, well, a constant. A mutable variables must have an explicit type because you can elect to initialize it with undefined like in

var a3: [3][]const u8 = undefined;

in this case it is clear that specific number 3 cannot be replaced with placeholder _.

Constants on the other hand cannot change and its type can be completely inferred from the initizalizer.

1 Like

Didn’t really get what you meant by:

This works:

const std = @import("std");

test {
    var leet = [_]usize{ undefined, 1336 };
    leet[1] += 1;
    std.debug.print("{d}\n", .{leet});
}
1 Like