익명 구조체 리터럴(Anonymous Struct Literals)
익명 구조체 리터럴(Anonymous Struct Literals)
구조체를 만들 때, 그 구조체의 타입을 항상 적어줘야 하는 건 아니에요. Zig는 리터럴의 구조체 타입을 생략하는 걸 허용합니다.
리터럴의 결과가 coerced될 때, 구조체 리터럴은 result location을 그대로 직접 인스턴스화해요. 복사가 일어나지 않습니다. 코드로 볼게요.
본문
만약 result location에 타입이 주어져 있다면, 그 타입을 써주는 대신 .으로 시작하는 익명 형태를 그대로 놓을 수 있어요.
const std = @import("std");
const expectEqual = std.testing.expectEqual;
const Point = struct { x: i32, y: i32 };
test "anonymous struct literal" {
const pt: Point = .{
.x = 13,
.y = 67,
};
try expectEqual(13, pt.x);
try expectEqual(67, pt.y);
}
$ zig test test_struct_result.zig
1/1 test_struct_result.test.anonymous struct literal...OK
All 1 tests passed.
pt의 타입을 보면 Point라고 명시되어 있죠. 그래서 리터럴 쪽에서는 .x, .y만 값으로 채워주면 됐어요. 여기서 중요한 건 리터럴이 result location을 직접 인스턴스화한다는 점이에요. 일단 먼저 타입이 명시된 경우를 봤는데, 이번에는 타입이 아예 없는 상황을 살펴볼게요.
구조체 타입은 추론될 수도 있어요. 아래 예시의 result location은 타입을 포함하지 않는데, 이 경우 Zig가 타입을 직접 추론합니다.
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
test "fully anonymous struct" {
try check(.{
.int = @as(u32, 1234),
.float = @as(f64, 12.34),
.b = true,
.s = "hi",
});
}
fn check(args: anytype) !void {
try expectEqual(1234, args.int);
try expectEqual(12.34, args.float);
try expect(args.b);
try expectEqual('h', args.s[0]);
try expectEqual('i', args.s[1]);
}
$ zig test test_anonymous_struct.zig
1/1 test_anonymous_struct.test.fully anonymous struct...OK
All 1 tests passed.
check 함수의 매개변수는 anytype이에요. 그렇기 때문에 .{...} 형태로 전달된 완전히 익명인 구조체가 하나의 타입으로 추론되고, 함수 안에서 args.int, args.float처럼 필드에 접근할 수 있게 됩니다.