ざっくりとしたZigの紹介

2022/07/15に公開

BunのおかげでZigに注目する人が増えたように感じます。
個人的にZigを使ってる人間として紹介がてら自分のZigに対する印象を書いていきます。

どんな言語か(公式)

「堅牢で最適で再利用可能なソフトウェアを維持するための汎用プログラミング言語」
https://ziglang.org/

公式のより詳しい紹介はこちら
https://ziglang.org/learn/overview/

Cをベースに現代的な機能を追加している

Raylibのサンプルコード

// raylib.comから引用(いくつかのコメントを削除)
#include "raylib.h"

int main(void)
{
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");

    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second

    // Main game loop
    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        BeginDrawing();

            ClearBackground(RAYWHITE);

            DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);

        EndDrawing();
    }

    CloseWindow();        // Close window and OpenGL context

    return 0;
}

公式のRaylibを呼び出すサンプルコード

const ray = @cImport({
    @cInclude("raylib.h");
});

pub fn main() void {
    const screenWidth = 800;
    const screenHeight = 450;

    ray.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
    defer ray.CloseWindow();

    ray.SetTargetFPS(60);

    while (!ray.WindowShouldClose()) {
        ray.BeginDrawing();
        defer ray.EndDrawing();

        ray.ClearBackground(ray.RAYWHITE);
        ray.DrawText("Hello, World!", 190, 200, 20, ray.LIGHTGRAY);
    }
}

基本的な文法はCに近くCを知っているなら公式のReferenceを読めばとりあえず書けると思います。

コード内にあるようにdeferや他にもOptionalsや型推論など現代的な機能が追加されています。
なので素のCを書くより快適に書けます。

Cのおかしなところは修正されている

Cっぽい言語ですがCの奇妙な動作の数々は修正されています(順序だけ決まった型のサイズや暗黙の型変換など、ここに記すには余白が狭すぎる)
なのでCの文法以外の不満も軒並み解消されています。

ビルドシステム自体もZigコンパイラに付属しているのでC++のようにカオスに乱立することは無いです。

構造体と関数ベースのプログラミング

OOPを支援する機能やRustのTraitのように型を拡張する機能は存在しません。
Cと同じく構造体と関数をベースにプログラミングをしていきます。

ただしGenericsの導入やUnionの改善が行われているので特別な機能が無くても書きやすいようにはなっています。

メモリは手動で管理する

GCやBorrow Checkerのように言語側でメモリを管理する仕組みは存在しません。
メモリの管理はプログラマの役割でありプログラマを信頼しているタイプの言語です。

ただしCのmalloc/freeスタイルではなくAllocatorベースでメモリ管理を行います。

// ziglearn.orgから引用
const std = @import("std");
const expect = std.testing.expect;

test "allocation" {
    const allocator = std.heap.page_allocator;

    const memory = try allocator.alloc(u8, 100);
    defer allocator.free(memory);

    try expect(memory.len == 100);
    try expect(@TypeOf(memory) == []u8);
}

defer allocator.free(memory);のようにすればスコープを抜けた際に自動的に解放されます。
そもそも確保したメモリ自体をAllocatorが記憶しているので使用済みになったら全てを開放することもできます。

なのでCよりはメモリ管理は行いやすいです。

ZigコンパイラはCコンパイラでもある

ZigコンパイラでCをコンパイルできます。
なのでZigのビルドシステムでCをコンパイルしてZigプログラムとリンクする事もできます。

例で出したRaylibをソースからビルドしてZigから呼び出し、Windows向けLinux向けにクロスコンパイルも行えます。

単純にc toolchainとしても有用でUberではZigをプログラミング言語としてではなくc toolchainとして使用しています。
https://jakstys.lt/2022/how-uber-uses-zig/
https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html

高いCとの親和性

const ray = @cImport({
    @cInclude("raylib.h");
});

Raylibのサンプルのように直接ヘッダーファイルを読み取ることができます。
なのでラップすることなく直接ZigのコードからCを呼び出すこともできます。

逆にZigで書いたコードをC向けにエクスポートすることも可能です。

export fn add(a: i32, b: i32) i32 {
    return a + b;
}

メモリ管理もお互い手動で、Cと基本的な文法が近く、Zig自体がCコンパイラということも有って障壁無くCと連携することができます。

機能の新規性は薄い

Zigならではのキラー機能というモノはあまりありません。
単純にCに他の言語で見られるような便利な機能をいくつか追加したような言語です。

ただcomptimeなどzig特有の機能自体はあります。

シンプルであることを強く意識している

シンプルというのは色々な意味を含みますがZigの場合は「簡素」であることを強く意識していると感じます。
メモリは追跡しない(GCレス)、オペレーター演算子のオーバーロードは出来ない、Interfaceはライブラリレベルで実装など機能を極力絞る形でシンプルさを維持しています。

標準ライブラリは貧弱

標準ライブラリは貧弱です。
ただしVer1.0にヒットしておらず目下の目標はセルフホストコンパイラの出荷なので仕方ないと言えます。

今後、開発が進めば充実すると思います。

ドキュメント・情報は少ない

同じくVer1.0前の言語であるので致し方ないところです。

公式のReference:
https://ziglang.org/documentation/master/

ziglearn.org:
https://ziglearn.org/

コミュニティ運営の情報サイト:
https://zig.news/

あたりがおススメのドキュメントです。

高速化のための仕組み?

Bunで有名になったので、どうしてZigだと高速にプログラムを動作させられるのか気になった人もいるかと思います。
が、Zigの中身はLLVMなのでRustやC/C++(Clang)と比べて特別早くなるような仕組みは無いです。

なのでBunが早いのは作者の方が最適化を頑張ったからBunは速いという結論になってしまいます。

一応、Zigがパフォーマンス的に有利な点を書くと:

  • 隠された制御フローが無く知らないうちにコストを支払っていたという状況になりにくい
  • メモリレイアウトを操作しやすいのでデータの配置をCPUキャッシュに最適化しやすい

他にも金融向けの高速DBがZigで開発されているのでパフォーマンスを求めるソフトウェアへの適性自体は高いです。
https://www.tigerbeetle.com/

安全性

Rustほどでは無いですがZig自体は安全性を意識している言語です。

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

Spatial memory safety. Mostly runtime mitigations. Nearly identical in both zig and rust. These are easy to implement and probably sufficiently non-controversial that any new systems language will have similar features.

とあるように空間的なメモリの安全性は担保しようとしています。

またUndefined Behaviorについても全てを列挙してRuntimeでキャッチできるように開発が進められています。

どんな言語か(個人の印象)

個人的な印象は「まともになったC言語」。

よく言語の評でBetter Cというものを見かけますが、Zigは文法・機能だけでなくCの実行環境を改善するという意味でもBetter Cな言語だと感じます。

単純にCより良い言語を目指すのではなく、Cの実行環境自体を改善しつつCの置き換えを狙っているのが他のCの置き換えを狙う言語に比べて面白い所です。

さいごに

個人的には良い言語だと思うので気になったら触ってみてください。

Discussion