プログラミング言語紹介:Zig
このページは2022/12/05開催の広島市立大学CA研トークセッション用の資料です。
自己紹介
河野雄也
プログラミング言語および開発支援ツールに興味がある
趣味はSF小説の表紙買い、Twitter、ニチアサの玩具収集
https://scrapbox.io/files/6388668651b215001d49cea3.png
今日話すこと
プログラミング言語好きの間で話題の言語Zigを紹介
言語全体のOverviewというより、より具体的かつ特徴的な言語機能やデザインの紹介にフォーカス
Zig
一言で言えば「すごくイマドキなC」
ポータビリティ重視。
小さく単純な言語を目指している。
ポータビリティ重視
どんな環境でも(例えばヒープ領域がないとか)動く。
GCも賢いリージョン解析もない。メモリ管理はプログラマの責任。
メモリアロケーションが必要な関数はすべてアロケータを引数に取る。
code:rs
const std = @import("std");
const Allocator = std.mem.Allocator;
const expect = std.testing.expect;
// テストを書くための構文がある
// エラーを返しうるvoid関数としてテストを書く
test "using an allocator" {
var buffer: 100u8 = undefined; // FixedBufferAllocatorはその名の通りスタック上に固定長のバッファを用意するアロケータ
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();
// 連結後の文字列を保持するためにメモリアロケーションが必要
const result = try concat(allocator, "foo", "bar");
try expect(std.mem.eql(u8, "foobar", result));
}
fn concat(allocator: Allocator, a: []const u8, b: []const u8) ![]u8 {
const result = try allocator.alloc(u8, a.len + b.len);
std.mem.copy(u8, result, a);
std.mem.copy(u8, resulta.len.., b); return result;
}
小さく単純な言語
型をコンパイル時定数として扱い、ジェネリクスを実現。
ジェネリクスのための構文はない。関数の引数として型を渡す。
モジュールすらconstな構造体として扱う。
code:rs
// stdはstd.zigで定義される無名の構造体
const std = @import("std");
// stdのdebugフィールドのassertフィールド、
// つまりstd.debugパッケージのassert関数
const assert = std.debug.assert;
test "types are values" {
const T1 = u8;
const T2 = bool;
assert(T1 != T2);
const x: T2 = true;
assert(x);
}
code:rs
const std = @import("std");
// これがほんとの型関数
fn List(comptime T: type) type {
return struct {
items: []T,
len: usize,
};
}
pub fn main() void {
var buffer: 10i32 = undefined; // List(i32) = struct { items: []i32, len; usize }
var list = List(i32){
.items = &buffer,
.len = 0,
};
std.debug.print("{d}\n", .{list.items.len});
}
ほかにもおもしろ機能がいろいろ
Cソースコードのコンパイル機能
大量の未定義動作
算術オーバーフローは未定義でコンパイルエラー
ちょっとRubyっぽさを感じる制御構文
code:rs
for (items) |value| {
if (value == 0) {
continue;
}
sum += value;
}