简介及更新
你好呀! (本·克诺比致敬)自从我上一篇博客文章以来已经有一段时间了,在 2024 年结束时我一直忙于做工作。关于 Autograd 优化的上一篇文章的一些更新:它已经达到迭代 02,我将在不久的将来写它。
在这篇文章中,我们将采用一些简单的东西(泛型),我们将看到不同语言的不同实现。
泛型
泛型允许安全地为多种数据类型重用代码。 Rust 和 Zig 等现代语言都内置了泛型,但 C 中没有这样的泛型。
该代码实际上取自Rust 书籍:
该程序演示了 Rust 中泛型的使用。此处使用泛型可以实现灵活且类型安全的代码,可以处理不同的数据类型,而无需为每种类型重写代码。
锈
对上一节中提供的程序进行一些解释:
- 创建一个 Point 结构体,并将 X1 和 Y1 作为类型参数。
- 为 Point 结构实现 mixup 方法。
该程序展示了通过使用泛型来处理不同数据类型的能力。
之字形
用 Zig 编写的相同程序:
const std = @import("std"); const print = std.debug.print; pub fn Point(comptime X1: type, comptime Y1: type) type { return struct { x: X1, y: Y1, const Self = @This(); pub fn mixup( self: Self, comptime X2: type, comptime Y2: type, other: Point(X2, Y2) ) Point(X1, Y2) { return .{ .x = self.x, .y = other.y, }; } }; } pub fn main() void { const p1 = Point(i32, f64){ .x = 5, .y = 10.4 }; const p2 = Point([]const u8, u8){ .x = "Hello", .y = 'c' }; const p3 = p1.mixup([]const u8, u8, p2); print("p3.x = {}, p3.y = {c}\n", .{ p3.x, p3.y }); }
它具有相同的输出,但正如您所看到的,在实现上有些不同:
- 创建一个泛型函数,返回一个新的结构类型,其中 X1 和 Y1 作为字段。
- mixup 函数返回一个新点,在其中混合来自不同点的值。
这表明程序成功地组合了来自不同点的 x 和 y 值,即使类型不同。
C
即使 C 没有内置泛型,我们也可以编写自己的泛型来模拟在 Rust 和 Zig 版本中得到的相同结果。
手动确定类型
- 定义一组自定义数据类型和结构来表示不同类型的数据。在 C 版本中,我们使用枚举、联合和结构。
- 数据结构有两个成员:存储不同类型数据的联合体和指定联合体中存储的数据类型的枚举。
#include <stdio.h> typedef enum { INT, DOUBLE, CHAR, STRING } DataType; typedef struct { union { int i; double d; char c; char* s; } data; DataType type; } Data; typedef struct { Data x; Data y; } Point;
接下来是打印功能:
- print_data:采用数据结构作为参数,并根据类型成员打印其值。
- print_point:采用 Point 结构并打印出值。
void print_data(Data data) { switch (data.type) { case INT: printf("%d", data.data.i); break; case DOUBLE: printf("%f", data.data.d); break; case CHAR: printf("%c", data.data.c); break; case STRING: printf("%s", data.data.s); break; default: printf("Unknown type"); } } void print_point(Point p) { printf("px = "); print_data(px); printf(", py = "); print_data(py); printf("\n"); }
混合函数:
- 本质上,该函数交换两个不同输入点的值。
Point mixup(Point self, Point other) { Point result; result.x = self.x; result.y = other.y; return result; }
最后是主要功能:
- 即使点(p1 和 p2)具有不同的数据类型,由于使用了联合和枚举(如前所述),程序也能正常运行。
- 输出:
px = 5, py = c
int main() { Point p1; p1.x.data.i = 5; p1.x.type = INT; p1.y.data.d = 10.4; p1.y.type = DOUBLE; Point p2; p2.x.data.s = "Hello"; p2.x.type = STRING; p2.y.data.c = 'c'; p2.y.type = CHAR; Point p3 = mixup(p1, p2); print_point(p3); return 0; }
自动检测类型
该程序有一个不同版本,可以自动检测类型。在前面的代码中,我们需要手动确定类型,如果我们运行自动化系统,这可能会很不方便或完全无法使用。
我把自动检测版本放在这里。
接下来
我可能会探索其他现代编程语言功能并了解它们之间的不同实现,尤其是 C 中不可用的功能。
原文: https://hwisnu.bearblog.dev/generics-implementation-in-rust-zig-and-c/