Skip to content

Proposal: Add String to the type system #7734

Closed
@mlarouche

Description

@mlarouche

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:

 fn print(value: anytype, result_buffer: *StringBuffer) !void {
    switch (@typeInfo(@TypeOf(value))) {
        .Enum => {
            try result_buffer.appendSlice(@tagName(value));
        },
        else => {
            try std.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
        },
    }
}

Now I need to do this:

fn print(value: anytype, result_buffer: *StringBuffer) !void {
    switch (@typeInfo(@TypeOf(value))) {
        .Enum => {
            try result_buffer.appendSlice(@tagName(value));
        },
        .Array => |array_info| {
            if (array_info.child == u8) {
                try std.fmt.formatType(value, "s", .{}, result_buffer.writer(), std.fmt.default_max_depth);
            } else {
                try std.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) {
                            try std.fmt.formatType(value, "s", .{}, result_buffer.writer(), std.fmt.default_max_depth);
                        } else {
                            try std.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
                        }
                    },
                    else => {
                        try std.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
                    },
                },
                .Many, .C, .Slice => {
                    if (ptr_info.child == u8) {
                        try std.fmt.formatType(value, "s", .{}, result_buffer.writer(), std.fmt.default_max_depth);
                    } else {
                        try std.fmt.formatType(value, "", .{}, result_buffer.writer(), std.fmt.default_max_depth);
                    }
                },
            }
        },
        else => {
            try std.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.
pub fn formatType(
    value: anytype,
    comptime fmt: const string,
    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 => {
    return formatValue(value, fmt, options, writer);
},
.Bool => {
    return formatBuf(if (value) "true" else "false", options, writer);
},
.String => |string_info| {
},
  • Expectation of new users

Consider a new user that try formatting for the first time.

const std = @import("std");

pub fn main() !void {
     const msg = "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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions