There is two kinds of ord function in std library of zig 0.13.0:
std.math.ord
for Tstd.mem.ord
for[]T
Is can provide other ord function for both T and []T
? The reason for that is some scenario need a comparable field being key when implement some structure like ord Tree:
pub fn Tree(comptime K: type, comptime V: type) type {
return struct {
root: ?*Node,
allocator: std.mem.Allocator,
const Self = @This();
const Node = struct {
key: K, // the key must be comparable, but now can't use either std.mem.order or std.math.order directly.
value: V,
left: ?*Node,
right: ?*Node,
allocator: std.mem.Allocator,
fn insert(node: *Node) (older_value: ?V, root: *Node) {
const order = // an order function for both T and []T;
switch (order) {
.eq => // emit
.lt => // emit
.gt => // emit
}
}
}
}
}
It is great if std library have an implementation like this:
fn Ord(comptime K: type) type {
return struct {
pub fn ord(a: K, b: K) std.math.Order {
if (comptime is_array_or_slice(K)) {
const typeinfo = @typeInfo(K);
const child_type = if (typeinfo == .Array) typeinfo.Array.child else if (typeinfo == .Pointer) typeinfo.Pointer.child else unreachable;
return std.mem.order(child_type, a, b);
} else {
return std.math.order(a, b);
}
}
fn is_array_or_slice(comptime T: type) bool {
const typeinfo = @typeInfo(T);
if (typeinfo == .Array) {
return true;
} else if (typeinfo == .Pointer) {
const pointer = typeinfo.Pointer;
return pointer.size == .Slice or pointer.size == .Many;
}
return false;
}
};
}
test Ord {
const ord = Ord([]const u8);
assert(ord.ord("A", "A") == .eq);
assert(ord.ord("A", "B") == .lt);
const ord2 = Ord(i32);
assert(ord2.ord(1, 1) == .eq);
assert(ord2.ord(1, 2) == .lt);
}