#Returning a formatted string

1 messages · Page 1 of 1 (latest)

silk lily
#

For can I get

pub fn stringify(self: Value) []u8 {
        var l = std.ArrayList(u8);
        defer l.deinit();
        std.fmt.allocPrint(
            l,
            switch (self.get_type) {
                .NAN => "NaN",
                .INTEGER, .FLOAT => "{d}",
                .BOOLEAN => "",
            },
            .{self.value},
        );

        return l.Slice();
    }

to compile?

exotic relic
#

first off, allocPrint requires an allocator, since it's, allocating.

#

i recommend you pass in an allocator with stringify function

silk lily
#

right yeah

exotic relic
#

pub fn stringify(self: Value, alloc: std.mem.Allocator)

#

you know, there is a much better way to do this in general

silk lily
#

What is it?

#

oh. you mean writing to a buffer in sequence?

exotic relic
#

because of how std.fmt.format works, if you place a function called format into Value, itll call it instead

#

so you can place a function into Value like this:

pub fn format(
    value: Value,
    comptime fmt: []const u8,
    options: std.fmt.FormatOptions,
    writer: anytype,
) !void {}
#

and just print to the writer with try writer.print("something", .{foo});

silk lily
#

hang on. like this?

pub fn format(
        self: Value,
        comptime fmt: []const u8,
        options: std.fmt.FormatOptions,
        writer: anytype,
    ) !void {
        _ = fmt;
        _ = options;
        const str = switch (self.get_type) {
            .NAN => "NaN",
            .INTEGER, .FLOAT => "{d}",
            .NONE => "none",
            .PTR => "ptr to {x}",
            .BOOLEAN => if (self.decode_bool()) {
                "true";
            } else {
                "false";
            },
        };
        try writer.print(str, .{self.value});
    }
#

also yeah if statements might not work that way

exotic relic
#

that's almost right

#

just dont use brackets with the if statement

#
 if (self.decode_bool()) "true" else "false",
silk lily
#

ah I remember now

#

I did that a while ago, I just forgot

#

will it compile if writer is an Anytype?

exotic relic
#

yes

silk lily
#

oh, will that be resolved at compile time or something

exotic relic
#

yes

silk lily
#

I see

#

ok, thanks

#

so, how would I use this again?

exotic relic
#

what is your end goal here?

void parrot
#

To answer the original question:

fn to_string(x: X, ally: Allocator) ![]const u8 {
    var out = std.ArrayList(u8).init(ally);
    errdefer out.deinit();
    ...
    return try out.toOwnedSlice();
}

But indeed, you don't necessarily want to have this kind of function, because you almost always want to format this string as part of another string - and so, using some sort of writer is better.

fn to_writer(x: X, w: anytype) !void {
    ...
}

And indeed, if you are only doing this for the purposes of debugging or otherwise just printing it out, then you can consider overriding how {} formats a value for stuff like std.debug.print -- which is what that fn format function does.

exotic relic
#

if your end goal is to create a string with this format, you can now use allocPrint

#

you will use it like this:

pub fn stringify(self: Value, alloc: std.mem.Allocator) ![]const u8 {
    return std.fmt.allocPrint(
        alloc,
        "{}",
        .{self.value},
    );
}
#

and std.fmt.format will auto call that format function you just made

silk lily
#

my end goal is to write a test to verify the output of the value

#
const alloc = testing.allocator;
test "test float" {
    const val = Value.encode_float(-512.1234).stringify(alloc);
    try testing.expectEqual("-512.1234", val);
}
#

oh my god how do I compare strings

exotic relic
#

std.mem.eql

silk lily
#

How can I use that with expectequal? Since I would like it to print if it's wrong

    try testing.expectEqual("-512.1234", val);```
#

or print what the wrong output is

steep plaza
#

expectEqualStrings

silk lily
#

oh lol

steep plaza
silk lily
#

it seems to work

steep plaza
#

oh cool

#

i wonder why 😅