Keith Kurson DigitalOcean hostingini UpCloudga kochirdi
Shaxsiy saytlar va kichik loyihalarni DigitalOcean'dan UpCloudga ko'chirish tajribasi, Deploy vositasi arxitekturasi va migratsiya bosqichlari haqida batafsil ma'lumot.

Refleksiya dasturiy ta'minotning o'z strukturasi ustida ish yuritish imkoniyatini beradi. C++ (kelajakdagi refleksiya qo'llab-quvvatlash bilan), Zig va C3 tillari compile-time refleksiya imkoniyatlariga ega. Bu tillar yordamida dasturchilar turlar, enumeratorlar va struct a'zolarini compile-time da tahlil qilishlari mumkin. Bu maqolada biz bu tillarning compile-time refleksiya qobiliyatlarini taqqoslaymiz.
C3 — bu o'zbek tilidagi dasturlash tilidir. U o'quvchanlik, samaradorlik, minimalizm va C/C++ dasturchilariga tanishlikni ta'minlaydi. C3da og'ir runtime, garbage collection, istisnolar yoki RAII yo'q. Bundan tashqari, u C ABI mosligi bilan to'liq qo'llab-quvvatlanadi.
1enum class Color { Red, Green, Blue };2
3template <typename E>4constexpr std::string_view enum_to_string(E value) {5 template inline for (constexpr auto r : std::meta::enumerators_of(^^E)) {6 if (value == [:r:]) {7 return std::meta::identifier_of(r);8 }9 }10 return "Unknown";11}12
13int main()14{15 Color color = Color::Red;16 printf("%s", enum_to_string(color));17
18 return 0;19}
C3da compile-time ijro uchun maxsus sintaksis ishlatiladi: barcha o'zgaruvchilar va boshqaruv konstruksiyalari $ belgisi bilan boshlanadi. Bu dasturchiga compile-time da ijro etiladigan kodni aniqlash imkonini beradi. C3da makrolar compile-time baholash va refleksiya uchun ishlatiladi.
C3 makrolari C preprocessor makrolarini almashtirish uchun mo'ljallangan. Ular compile-time baholashni takomillashtiradi, bu esa IDEga do'stona, cheklangan compile-time ijro imkoniyatini ta'minlaydi.
1const Color = enum {2 RED,3 GREEN,4 BLUE,5
6 pub fn to_string(color: Color) []const u8 {7 switch (color) {8 .RED => return "red",9 .GREEN => return "green",10 .BLUE => return "blue",11 }12 }13};14
15pub fn main() !void {16 const c: Color = .BLUE;17 std.debug.print("{s}", .{c.to_string()});18 // Outputs:19 // blue20}
Enum to string aylantirish — bu enum qiymatlarini matn shaklida ifodalash usuli. Biz bu usulni C++, Zig va C3 tillarida taqqoslaymiz.
C++da enum to string aylantirish uchun template va meta-programming ishlatiladi. Bu usul juda murakkab va o'quvchan emas.
1enum Color { RED, GREEN, BLUE }2
3macro String enum_to_string($enum_val)4{5 var $EnumType = $Typeof($enum_val);6 $foreach $val : $EnumType::values:7 $if $val == $enum_val:8 return $val.description;9 $endif10 $endforeach11}12
13fn void main()14{15 Color $color = RED;16 String $color_name = enum_to_string($color);17 io::printfn("%s", $color_name);18}
Zigda enum to string aylantirish uchun har bir enumga maxsus metod qo'shish kerak. Bu umumiy yondashuv emas.
C3da enums maxsus xususiyatlarga ega. Masalan, enum qiymatini o'qiladigan shaklda chiqarish mumkin. Misol uchun, io::printfn("\%s", Color.RED) kod RED ni chiqarib beradi, lekin 0 ni chiqarib bermaydi.
1enum Color : uint (String str_repr, char amount_of_red)2{3 RED { "Red Color", 255 }4 BLUE { "Blue Color", 0 }5}6
7fn void log_color(Color c)8{9 io::printfn("%s %s", c.str_repr, c.amount_of_red); // Outputs: Red Color 25510}
Enumning asl qiymatini olish uchun .ordinal yoki asl turga o'tkazish mumkin. Bundan tashqari, enumga turli turdagi qiymatlar bog'lash mumkin.
Struct introspection — bu struct a'zolarini compile-time da tahlil qilish usuli. Biz bu usulni C++, Zig va C3 tillarida taqqoslaymiz.
1struct Person {2 std::string_view name;3 int age;4 double height;5};6
7template <typename T>8void print_struct_fields(const T& obj) {9 std::cout << std::meta::identifier_of(^^T) << " details:\n";10
11 template inline for (constexpr auto member : std::meta::nonstatic_data_members_of(^^T)) {12 constexpr std::string_view member_name = std::meta::identifier_of(member);13 std::cout << " " << member_name << ": " << obj.[:member:] << "\n";14 }15}16
17int main() {18 Person alice{"Alice Smith", 30, 1.75};19 print_struct_fields(alice);20 /*21 Outputs:22 Person details:23 name: Alice Smith24 age: 3025 height: 1.7526 */27}
C++da struct introspection uchun template va meta-programming ishlatiladi. Bu usul juda murakkab va o'quvchan emas.
Zigda struct introspection uchun comptime funksiyalar va bloklar, inline for tsiklari va type-introspection builtins ishlatiladi. Bu usul zamonaviy va o'quvchan.
1const Person = struct {2 name: []const u8,3 age: i32,4 height: f64,5};6
7fn printStructFields(value: anytype) void {8 comptime {9 std.debug.assert(@typeInfo(@TypeOf(value)) == .@"struct");10 }11 inline for (@typeInfo(@TypeOf(value)).@"struct".fields) |field| {12 switch (field.type) {13 []const u8 => {14 std.debug.print("{s}: {s},\n", .{ field.name, @field(value, field.name) });15 },16 else => {17 std.debug.print("{s}: {any},\n", .{ field.name, @field(value, field.name) });18 },19 }20 }21}22
23pub fn main() !void {24 const alice = Person{25 .name = "Alice Smith",26 .age = 30,27 .height = 1.75,28 };29
30 std.debug.print("Person Details:\n", .{});31 printStructFields(alice);32 // Outputs:33 // Person details:34 // name: Alice Smith35 // age: 3036 // height: 1.75000037}
C3da struct introspection uchun maxsus sintaksis ishlatiladi. Bundan tashqari, C3da optional pre-conditions yoki 'contracts' ishlatiladi, bu input validatsiyasini yaxshilaydi. Ular compile-time da ijro etiladi, agar mumkin bo'lmasa, runtime da ijro etiladi.
Barcha kuzatilgan tillar compile-time refleksiya imkoniyatlariga ega. Bu serializers, debug printers va generic helpers uchun foydali. Ammo, ergonomik jihatdan farq bor. C++ bu imkoniyatlarni template mashinasi va splices orqali ta'minlaydi, C3 esa makro tizimi va compile-time ijro uchun maxsus sintaksis orqali bu imkoniyatlarni o'quvchan va ifodalovchi qiladi.
1struct Person2{3 String name;4 int age;5 double height;6}7
8<*9 @require @kindof($val) == STRUCT : "Expected a struct" // (1)10*>11macro void print_struct_fields($val)12{13 var $Type = $Typeof($val);14 $foreach $field : $Type::members:15 io::printfn("\t%s: %s", $field.name, $val.$field);16 $endforeach17}18
19fn void main()20{21 Person $alice = {"Alice Smith", 30, 1.75};22 io::printfn("Person details: ");23 print_struct_fields($alice);24 /*25 Outputs:26 Person details:27 name: Alice Smith28 age: 3029 height: 1.75000030 */31}
Zigda makrolar yo'q, u comptime funksiyalar va bloklar, inline for tsiklari va type-introspection builtins ishlatadi. Bu ham zamonaviy va o'quvchan usul.
Shaxsiy jihatdan, men C3ni juda umidli tizim dasturlash tili deb bilamanki, u ko'proq e'tibor talab qiladi. Barcha C++ va Zigni bilishadi, lekin C3da shunday marketing yo'q, ammo u Zig, Odin yoki boshqa yangi tizim dasturlash tillari bilan raqobatlashishi mumkin.
1struct Range { int lo; int hi; }2
3struct Config4{5 [[=Range{ 1, 65535 }]] int port;6 [[=Range{ 1, 256 }]] int max_threads;7 [[=Range{ 100, 30000 }]] int timeout_ms;8}9
10template<typename T>11consexpr bool validate(const T& obj)12{13 constexpr auto context = std::meta::access_context::current();14 template for (constexpr auto member: define_static_array(15 nonstatic_data_members_of(^^T, context)) {16 template for (constexpr auto annotation : define_static_array(17 annotations_of_with_type(member, ^^Range))) {18 auto [lo, hi] = extract<Range>(annotation);19 if (obj.[:member:] < lo) return false;20 else if (obj.[:member:] > hi) return false;21 })22 return true;23}24
25static_assert(validate(Config{ 1000, 50, 20000 }));26static_assert(validate(Config{ 0, 0, 0 })); // Fails to compile.
C3da har bir minor versiyada ko'p o'zgarishlar yo'q. U Zigdan ko'ra ancha barqaror. C3 0.8.x versiyalarida, 1.0 versiyasi yaqin. Roadmapga qarang.
C3 haqida ko'proq ma'lumot olish uchun rasmiy saytga murojaat qiling. Til haqida muhokama qilish yoki savollar bo'lsa, rasmiy C3 Discord serveriga qo'shiling.
Asl manba: nyr24.github.io