評価4: 型システムの実践 - 評価基準
評価の目的
この評価では、学生がZigの型システムの実践的な活用能力、特に安全な型変換、オプショナル型の使用、ユニオン型の理解を確認します。型安全性はZigプログラミングの核心です。
学習目標
- 安全な型変換を実装できる
- オプショナル型を適切に使用できる
- ユニオン型とタグ付きユニオンを理解し活用できる
- 型パラメータを使ったジェネリック関数を作成できる
- エラーハンドリングと型システムを統合できる
評価項目
1. 型変換ユーティリティ(20点)
| 項目 | 配点 | 評価基準 |
|---|---|---|
| **安全なキャスト** | 6点 | 6点:範囲チェックを含むsafeCast実装 4点:基本的な動作はするが範囲チェック不完全 2点:型変換のみで安全性なし 0点:動作しない |
| **文字列パース** | 5点 | 5点:エラー処理を含む完全なparseInteger実装 3点:基本的なパースは動作 0点:動作しない |
| **整数→文字列** | 5点 | 5点:allocatorを使った正しい実装とメモリ管理 3点:動作するがメモリ管理に問題 0点:動作しない |
| **浮動小数点→文字列** | 4点 | 4点:精度指定を含む完全な実装 2点:基本的な変換のみ 0点:動作しない |
実装チェックポイント:
fn safeCast(comptime T: type, value: i64) ?T {
const min = std.math.minInt(T);
const max = std.math.maxInt(T);
if (value < min or value > max) return null;
return @intCast(value);
}
fn parseInteger(comptime T: type, str: []const u8) !T {
return try std.fmt.parseInt(T, str, 10);
}
fn integerToString(allocator: std.mem.Allocator, value: i64) ![]u8 {
return try std.fmt.allocPrint(allocator, "{}", .{value});
}
2. オプショナル型の活用(20点)
| 項目 | 配点 | 評価基準 |
|---|---|---|
| **配列検索** | 5点 | 5点:findIndex関数が正しく動作し、見つからない場合nullを返す 3点:基本的な検索は動作 0点:動作しない |
| **最大値・最小値** | 6点 | 6点:maxValue/minValue両方が空配列でnullを返す 4点:一方のみ正しい 0点:動作しない |
| **デフォルト値処理** | 5点 | 5点:unwrapOrを使ったデフォルト値設定 3点:基本的な使用のみ 0点:理解不十分 |
| **オプショナルチェーン** | 4点 | 4点:mapOptionalを使った変換処理 2点:限定的な実装 0点:動作しない |
評価ポイント:
fn findIndex(comptime T: type, array: []const T, target: T) ?usize {
for (array, 0..) |item, i| {
if (item == target) return i;
}
return null;
}
fn maxValue(comptime T: type, array: []const T) ?T {
if (array.len == 0) return null;
var max = array[0];
for (array[1..]) |item| {
if (item > max) max = item;
}
return max;
}
3. ユニオン型とタグ付きユニオン(20点)
| 項目 | 配点 | 評価基準 |
|---|---|---|
| **Result型の定義** | 6点 | 6点:Success/Errorを含む完全なResult型定義 4点:基本的な定義のみ 0点:不完全 |
| **パターンマッチング** | 8点 | 8点:switch文で全てのケースを適切に処理 6点:主要なケースは処理 3点:限定的な処理 0点:理解不十分 |
| **型安全性** | 6点 | 6点:タグとペイロードの組み合わせを正しく使用 4点:基本的な使用のみ 0点:不適切 |
実装例:
const Result = union(enum) {
success: i32,
error_msg: []const u8,
pub fn isSuccess(self: Result) bool {
return switch (self) {
.success => true,
.error_msg => false,
};
}
};
4. ジェネリック関数(20点)
| 項目 | 配点 | 評価基準 |
|---|---|---|
| **型パラメータ使用** | 8点 | 8点:comptime型パラメータを正しく使用 6点:基本的な使用のみ 3点:理解が浅い 0点:使用できない |
| **型制約** | 6点 | 6点:適切な型制約とコンパイルエラー 4点:制約はあるが不完全 0点:制約なし |
| **実装品質** | 6点 | 6点:複数の型で動作し、エッジケースも処理 4点:基本的な型のみ対応 0点:限定的 |
ボーナス課題の評価
Bonus 1: 高度なオプショナル操作(15点)
| 配点 | 評価基準 |
|---|---|
| 15点 | flatMap、filterOptional、combineなど複数の高度な関数を実装 |
| 10点 | 2-3個の関数を実装 |
| 5点 | 1個のみ |
| 0点 | 未実装または動作しない |
Bonus 2: カスタムアロケータ(20点)
| 配点 | 評価基準 |
|---|---|
| 20点 | メモリプール、アリーナアロケータを実装し、適切に動作 |
| 15点 | 基本的なカスタムアロケータを実装 |
| 10点 | 部分的な実装 |
| 0点 | 動作しない |
Bonus 3: 型レベルプログラミング(15点)
| 配点 | 評価基準 |
|---|---|
| 15点 | @typeInfoを使った複雑な型操作を実装 |
| 10点 | 基本的な型情報の取得と使用 |
| 5点 | 限定的な使用 |
| 0点 | 理解不十分 |
Bonus 4: パフォーマンス比較(20点)
| 配点 | 評価基準 |
|---|---|
| 20点 | 詳細なベンチマークと分析レポート |
| 15点 | 基本的な測定と分析 |
| 10点 | 測定のみ |
| 0点 | 不完全 |
評価チェックリスト
マンダトリー要件
- [ ] Part 1の4つの関数すべてが動作する
- [ ] safeCastで範囲チェックが実装されている
- [ ] Part 2のオプショナル型関数が正しくnullを返す
- [ ] Part 3のユニオン型が適切に定義されている
- [ ] Part 3でswitch文による網羅的なパターンマッチング
- [ ] Part 4のジェネリック関数が複数の型で動作する
- [ ] メモリリークがない
- [ ] エラー処理が適切
- [ ] コンパイルエラーなく動作
コード品質
- [ ] 型注釈が適切
- [ ] allocatorの使用とdeferによる解放
- [ ] エラーメッセージがわかりやすい
- [ ] 変数名が意味を持つ
ボーナス要件
- [ ] Bonus 1: 複数の高度なオプショナル操作
- [ ] Bonus 2: カスタムアロケータの実装
- [ ] Bonus 3: 型レベルプログラミングの活用
- [ ] Bonus 4: ベンチマークと分析
- オプショナル型の理解
合格基準
| レベル | 点数 | 説明 |
|---|---|---|
| **優秀** | 90-100点 | 型システムを完全に理解し、高度な機能を活用できる |
| **良好** | 80-89点 | 基本的な型操作ができ、一部の高度な機能を使用 |
| **合格** | 70-79点 | 型の基礎を理解し、基本的な実装ができる |
| **要再提出** | 0-69点 | 型システムの理解が不十分、復習が必要 |
学習の手引き
効果的な学習方法
- ユニオン型の活用
- ジェネリックプログラミング
よくある間違いと対策
間違い1: オプショナルのアンラップ忘れ
// ❌ 間違い
const value: ?i32 = findValue();
print("{}", .{value}); // エラー: オプショナル型
// ✅ 正しい
if (findValue()) |value| {
print("{}", .{value});
}
間違い2: ユニオン型のタグ不一致
// ❌ 間違い
const result = Result{ .success = 42 };
const msg = result.error_msg; // パニック!
// ✅ 正しい
switch (result) {
.success => |val| print("{}", .{val}),
.error_msg => |msg| print("{s}", .{msg}),
}
時間配分の目安
- Part 1: 3-4時間
- Part 2: 3-4時間
- Part 3: 3-4時間
- Part 4: 3-4時間
- ボーナス: 8-12時間
- Zig Language Reference - Optional Type: https://ziglang.org/documentation/master/#Optional-Type
- Zig Language Reference - Tagged Union: https://ziglang.org/documentation/master/#Tagged-union
- Zig Standard Library - mem: https://ziglang.org/documentation/master/std/#std.mem
- Zig Learn - Chapter 1: https://ziglearn.org/chapter-1/
合計: 12-16時間(マンダトリー)、20-28時間(ボーナス込み)