Open13

Zig 言語を触ってみる

近年徐々に話題にあがりはじめている Zig という言語がある。

C 言語との ABI レベル相互運用が手軽にできるなど、低レイヤーがターゲットのプログラミング言語な気がしている。

https://qiita.com/bellbind/items/f2338fa1d82a2a79f290

Zig の安全性に対する評価は下記の記事にいろいろまとまっている。use-after-free や double free 、uninitialized memory などが none という評価ということは、そこまで安全性が重視された言語ではないということ?

https://scattered-thoughts.net/writing/how-safe-is-zig/

言語公式が推す売りポイントは

  • No hidden control flow.
  • No hidden memory allocations.
  • No preprocessor, no macros.

https://ziglang.org/

メモリの管理が適切に行われているのかはAllocatorの責任としていて、標準ライブラリのGeneralPurposeDebugAllocatorではdouble freeやリークを検出します。

https://github.com/andrewrk/zig-general-purpose-allocator

個人的な感想ですが、ヒープの使用はオプションとしているのでメモリ管理に関しては言語の仕組み側で管理するような事はしないのかなと。

ありがとうございます!なるほど。Zig の設計が少しわかってきた気がします😃

Zig プロジェクトは下記のようにして開始できる。

mkdir zig-sandbox
cd zig-sandbox
zig init-exe

すると、ディレクトリ内に下記のようにファイルやディレクトリができあがる。

❯ ls --tree
.
├── build.zig
└── src
   └── main.zig

生成された Hello, world するコードは下記。

const std = @import("std");

pub fn main() anyerror!void {
    std.log.info("All your codebase are belong to us.", .{});
}

ビルドして実行するには下記のコマンドを打つ。

zig build run

ようやく Hello, World できたw

const std = @import("std");

pub fn main() void {
    std.debug.print("Hello, {s}!\n", .{"World"});
}

https://ziglearn.org/

テストコードは同じファイル内に書けそうだけど、ちょっと詰まった。

書き方あってるんだろうか?Zig Learn に従って try expect を使用したら、コンパイルエラーに見舞われてテストが実行できなかった。zig-example というリポジトリがあって、そこで std.debug.assert を使っていたのでそれを使ってみている。

下記コードを参考にしてみた。

https://github.com/jonathangjertsen/zig-examples/blob/master/src/test.zig
const std = @import("std");
const assert = @import("std").debug.assert;

pub fn main() void {
    std.debug.print("Hello, {s}!\n", .{"World"});
}

test "while" {
    var i: i32 = 2;
    while (i < 100) {
        i *= 2;
    }
    assert(i == 128);
}

リポジトリはこれ。

https://github.com/jonathangjertsen/zig-examples/

ちなみに型推論とか効くのかなと思って、型注釈を消してみたら次のコンパイルエラーになった。別の型として認識されている?? var がどういう意味なのかをそもそも確かめる必要がありそう。

❯ zig test src/*.zig
./src/main.zig:9:5: error: variable of type 'comptime_int' must be const or comptime
    var i = 2;
    ^
./src/main.zig:10:12: note: referenced here
    while (i < 100) {
           ^

ありがとうございます!これはおもしろいですね。読んでみます。

if 文。

test "if statement" {
    const a = true;
    var x: u16 = 0;
    if (a) {
        x += 1;
    } else {
        x += 2;
    }
    assert(x == 1);
}

for 文。

最初、print の引数に2つ以上要素を割り当てる際にどうすればいいかわからなかった。.{} 内に受け取りたい引数をカンマ区切りで入れれば解決できた。

test "for" {
    const string = [_]u8{ 'a', 'b', 'c' };
    for (string) |character, index| {
        std.debug.print("character: {}, index: {} \n", .{ character, index });
    }
}

最後に fibonacci 。条件では || ではなく or を使う。

fn fibonacci(n: u16) u16 {
    if (n == 0 or n == 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

test "fibonacci" {
    const x = fibonacci(10);
    assert(x == 55);
}
ログインするとコメントできます