Problem
Since the change in PR #6870, now everytime we need to format a string, we need to specify {s} as a format specifier.
In my project https://github.com/mlarouche/stringtime/, my print method looked like this:
fnprint(value: anytype, result_buffer: *StringBuffer) !void {
switch (@typeInfo(@TypeOf(value))) {
.Enum=> {
tryresult_buffer.appendSlice(@tagName(value));
},
else=> {
trystd.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
},
}
}Now I need to do this:
fnprint(value: anytype, result_buffer: *StringBuffer) !void {
switch (@typeInfo(@TypeOf(value))) {
.Enum=> {
tryresult_buffer.appendSlice(@tagName(value));
},
.Array=>|array_info| {
if (array_info.child==u8) {
trystd.fmt.formatType(value, "s", .{}, result_buffer.writer(), std.fmt.default_max_depth);
} else {
trystd.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
}
},
.Pointer=>|ptr_info| {
switch (ptr_info.size) {
.One=>switch (@typeInfo(ptr_info.child)) {
.Array=>|info| {
if (info.child==u8) {
trystd.fmt.formatType(value, "s", .{}, result_buffer.writer(), std.fmt.default_max_depth);
} else {
trystd.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
}
},
else=> {
trystd.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
},
},
.Many, .C, .Slice=> {
if (ptr_info.child==u8) {
trystd.fmt.formatType(value, "s", .{}, result_buffer.writer(), std.fmt.default_max_depth);
} else {
trystd.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
}
},
}
},
else=> {
trystd.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
},
}
}This is far too many checks to shovel to the end user to know if the current type is a string.
Event std.fmt.formatType has to do this charade to know if the type is a string: Array, Pointer-To-One-Array, Pointer-To-Many, Pointer-To-C, Pointer-To-Slice and if the child type is u8.
The problem that #6870 fixed would have not occurred if the type system has a proper string type in the first place.
Advantages of having a proper string type in the type system
- Clarity of intent in the function signature.
pubfnformatType(
value: anytype,
comptimefmt: conststring,
options: FormatOptions,
writer: anytype,
max_depth: usize,
) @TypeOf(writer).Error!void {
}- Simplify reflection code for handling strings, Array and pointers/slice are now properly only array and pointers. No more special case for the u8 child type that every user of reflection. Many serialization code needs to know if the type is a string for special handling.
switch (@typeInfo(T)) {
.ComptimeInt, .Int, .ComptimeFloat, .Float=> {
returnformatValue(value, fmt, options, writer);
},
.Bool=> {
returnformatBuf(if (value) "true"else"false", options, writer);
},
.String=>|string_info| {
},Consider a new user that try formatting for the first time.
conststd=@import("std");
pubfnmain() !void {
constmsg="World!";
std.log.info("Hello, {}\n", .{msg});
}and see each value on an array printed instead of his string? It would be a really bad first impression of the language.
Problem
Since the change in PR #6870, now everytime we need to format a string, we need to specify {s} as a format specifier.
In my project https://github.com/mlarouche/stringtime/, my
printmethod looked like this:Now I need to do this:
This is far too many checks to shovel to the end user to know if the current type is a string.
Event
std.fmt.formatTypehas to do this charade to know if the type is a string: Array, Pointer-To-One-Array, Pointer-To-Many, Pointer-To-C, Pointer-To-Slice and if the child type is u8.The problem that #6870 fixed would have not occurred if the type system has a proper string type in the first place.
Advantages of having a proper string type in the type system
Consider a new user that try formatting for the first time.
and see each value on an array printed instead of his string? It would be a really bad first impression of the language.