Open7
Zig書いてみたい
Zig書いてみたいけど、どこから始めるのがいいだろうか?
やはりこの辺なのだろうか
この辺も良さそう。
まずはこれですかね。
mkdir hello-world
cd hello-world
zig init-exe
これで一応、構成はできた。
❯ zig build run
All your codebase are belong to us.
Run `zig build test` to run the tests.
よしよし
ここを読みながら少しずつやっていこう
For
test "for" {
const str = "hoge";
for (str) |c| {
std.debug.print("--- {} \n", .{c});
}
}
--- 111
--- 103
--- 101
なるほど。
文字列に関しては
これか。
うーん、後で理解しよう。
テストの書き方
Rustみたいに同じファイルに書くのが一般的なんだろうか?
fn addFive(x: u32) u32 {
return x + 5;
}
test "function" {
try expect(addFive(5) == 10);
}
try
って、なんだろうか?
Zig 入門 #8 - Errors - kawaken.dev
try は x catch |err| return err の糖衣構文になります。
なるほど、Rustの ?
と似たような雰囲気ですね。
Enum
const Suit = enum {
clubs,
spades,
diamonds,
hearts,
pub fn isClubs(self: Suit) bool {
return self == Suit.clubs;
}
};
test "enum method" {
try expect(Suit.spades.isClubs() == Suit.isClubs(.spades));
}
このメソッドの書き方おもしろいですねぇ。
ちなみに、これは
test "enum method" {
const Suit = enum {
clubs,
spades,
diamonds,
hearts,
pub fn isClubs(self: Suit) bool {
return self == Suit.clubs;
}
};
try expect(Suit.spades.isClubs() == Suit.isClubs(.spades));
}
こうするとコンパイルエラーになる
src/main.zig:60:30: error: use of undeclared identifier 'Suit'
pub fn isClubs(self: Suit) bool {
^~~~
なるほど。
Suit.isClubs(.spades)
この .spades
って、 Suit.spades
じゃなくていいんですね。
型推論できるから省略できるってことですかね。
Struct
特に疑問はないのでスキップ
Unions
const Result = union {
int: i64,
float: f64,
bool: bool,
};
test "simple union" {
var result = Result{ .int = 1234 };
result.float = 0.001;
}
main.zig:76:11: 0x1006bd57b in test.simple union (test)
result.float = 0.001;
^
ふむ、なるほど。
これ、どれを持っているか型からわからない?
だとするとどうやって使うんだろうか。
switch?
例えば
const Result = union {
int: i64,
float: f64,
bool: bool,
};
fn hogeResult(r: Result) void {
std.debug.print("--- {} \n", .{r.bool});
}
test "simple union" {
const result = Result{ .int = 1234 };
hogeResult(result);
}
こんな風にすると
panic: access of inactive union field
/src/main.zig:75:37: 0x100ac158f in hogeResult (test)
std.debug.print("--- {} \n", .{r.bool});
^
実行時エラーになりますね。
TaggedUnions
この為にタグ付きユニオンというのがあるらしい
const Result = union(enum) {
int: i64,
float: f64,
bool: bool,
};
fn hogeResult(r: Result) void {
switch (r) {
.int => |x| {
std.debug.print("--- {} \n", .{x});
},
.float => |x| {
std.debug.print("--- {} \n", .{x});
},
.bool => |x| {
std.debug.print("--- {} \n", .{x});
},
}
}
test "simple union" {
const result = Result{ .int = 1234 };
hogeResult(result);
}
こんな風に条件分岐できるようになりました。
Allocator & ArrayList
test "ArrayList" {
const eql = std.mem.eql;
const ArrayList = std.ArrayList;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var list = ArrayList(u8).init(allocator);
defer list.deinit();
try list.append('H');
try list.append('e');
try list.append('l');
try list.append('l');
try list.append('o');
try list.appendSlice(" World!");
std.debug.print("--- {s}\n", .{list.items});
try expect(eql(u8, list.items, "Hello World!"));
try list.appendSlice("=================================================================================================================================================================================================================================================================================");
std.debug.print("--- {s}\n", .{list.items});
}
--- Hello World!
--- Hello World!=================================================================================================================================================================================================================================================================================
とりあえず、GeneralPurposeAllocatorを使っておいても良さそうなので、そうしてみました。