Zigの不満点
string([]const u8)でswitchできない
'std.mem.eql'と大量のifでやるしかない。文字列比較の方法的に仕方ないんだろうけど、せめてmem.eqlのシンタックスシュガーとしてswitchでできるようにしてほしい
比較対象が静的に分かってる場合限定ですが、std.mem.eqlを書くのがクソだるい場合に、std.ComptimeStringMapstd.StaticStringMapをよく使います。
↑今は名前変わってたわ。うっかりうっかり。
そのままルックアップするもよし、comptimeで文字列リテラルを引数に取りenumを返す関数を用意してswitchで分岐するもよし。
comptimeで文字列リテラルを引数に取りenumを返す関数は、F#のActive Patternに着想を得ています。
構造体のプライベートフィールド
ファイル単位(std.mem.Allocatorとか)ならできるよね?まぁプライベートを挿入した結果OOPがメインストリームになったら最悪だけど
コンパイル時の型解決を許すのであればなんとか・・・。
fn PrivType(a: []const u8, b: u32) type {
return struct {
pub fn valA(self: @This()) []const u8 {
_ = self;
return a;
}
pub fn valB(self: @This()) u32 {
_ = self;
return b;
}
};
}
test "simple test" {
const sa = "123";
const sb = "456";
const a1, const b1 = comptime blk:{
const b = try std.fmt.parseInt(u32, sb, 0);
const t: PrivType(sa, b) = .{};
break :blk .{t.valA(), t.valB()};
};
std.debug.print("a: {s}, b: {}", .{a1, b1});
}
確かにgetterとして持たせることはできますね。
ただその方法だとインスタンスごとに関数が作られちゃって.textが肥大化するのと、何よりhackyでオーバーキルな感じがしちゃいますね... 💀
extern struct のフィールドが align(1) ではない
extern struct はフィールドの型に応じて勝手にパディングを入れる。
例えば u16 のフィールドは u16 アラインされるように1バイトのパディングを入れたりする。
自分の場合 extern struct を使うのは低レベルに定義されたデータ構造を表現する場合がほとんどだから、Cで言うところの __attribute__((packed)) がデフォルト動作であってほしい。
今のままだと、全てのフィールドに align(1) をつけるというアホほどめんどうなことをする必要がある。
Ref:
type が予約語
type を変数名に使いたいことがしばしばある。
Type とかにしてくれ。