解答4: 型システムの深い理解

概要

この解答では、Zigの型システムについて深く学びます。Zigは静的型付け言語であり、コンパイル時に型チェックが行われます。

Part 1: プリミティブ型

const std = @import("std");

pub fn main() void {
    // 任意ビット幅の整数型
    const u3_val: u3 = 7;
    const i3_val: i3 = -4;
    const u12_val: u12 = 4095;

    std.debug.print("u3: {} (max: {})\n", .{u3_val, std.math.maxInt(u3)});
    std.debug.print("i3: {} (range: {} to {})\n", .{i3_val, std.math.minInt(i3), std.math.maxInt(i3)});
    std.debug.print("u12: {} (max: {})\n", .{u12_val, std.math.maxInt(u12)});

    // 浮動小数点の特殊値
    const inf: f64 = std.math.inf(f64);
    const nan: f64 = std.math.nan(f64);
    std.debug.print("Infinity: {d}, NaN: {d}\n", .{inf, nan});
}

Part 2: 型変換

const std = @import("std");

pub fn typeConversions() void {
    // 安全な拡大変換
    const small: u8 = 100;
    const large: u16 = small;

    // @intCast - 縮小変換
    const big: i32 = 200;
    const byte: u8 = @intCast(big);

    // @floatCast - 浮動小数点変換
    const f64_val: f64 = 3.14159;
    const f32_val: f32 = @floatCast(f64_val);

    std.debug.print("Conversions: {}, {}, {d}\n", .{large, byte, f32_val});
}

Part 3: オプショナル型

const std = @import("std");

pub fn optionalDemo() void {
    var maybe_int: ?i32 = 42;

    // orelse でデフォルト値
    const value = maybe_int orelse 0;

    // if でアンラップ
    if (maybe_int) |val| {
        std.debug.print("Value: {}\n", .{val});
    }

    maybe_int = null;
    std.debug.print("Is null: {}\n", .{maybe_int == null});
}

ポイント解説

  • 型安全性: Zigはすべての型エラーをコンパイル時に検出
  • 明示的変換: 暗黙の型変換を最小限に抑制
  • オーバーフロー検出: 算術オーバーフローをランタイムでキャッチ
  • よくある間違い

    // 危険:オーバーフローの可能性
    var x: u8 = 255;
    x += 1; // パニック
    
    // 安全:ラップアラウンドを明示
    var y: u8 = 255;
    y +%= 1; // 0になる
    

    自己確認チェックリスト

  • [ ] プリミティブ型の範囲を理解しているか
  • [ ] 型変換の各種方法を正しく使えるか
  • [ ] オプショナル型の用途を説明できるか