Thread overview
Custom separator in array format
Jan 28, 2020
Malte
Jan 28, 2020
Simen Kjærås
Jan 28, 2020
Malte
January 28, 2020
I want to format an array using the %(...%) syntax. How can I change the separator? I tried to use ? and add it as additional parameter, but that doesn't seem to work on arrays:

import std;
void main()
{
    writeln("This works:");
    writefln("%,2?d", '_', 2000); // 20_00

    auto vec = [1000, 2000, 3000];
    writeln("This should fail (separator character expected) but the ? is just ignored:");
    writefln("%(%,2?d\t%)", vec); // 10,00	20,00	30,00
    writeln("This throws:");
    writefln("%(%,2?d\t%)", '_', vec); // std.format.FormatException@/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(2271): incompatible format character for integral argument: %(
}
January 28, 2020
On Tuesday, 28 January 2020 at 07:36:25 UTC, Malte wrote:
> I want to format an array using the %(...%) syntax. How can I change the separator? I tried to use ? and add it as additional parameter, but that doesn't seem to work on arrays:
>
> import std;
> void main()
> {
>     writeln("This works:");
>     writefln("%,2?d", '_', 2000); // 20_00
>
>     auto vec = [1000, 2000, 3000];
>     writeln("This should fail (separator character expected) but the ? is just ignored:");
>     writefln("%(%,2?d\t%)", vec); // 10,00	20,00	30,00
>     writeln("This throws:");
>     writefln("%(%,2?d\t%)", '_', vec); // std.format.FormatException@/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(2271): incompatible format character for integral argument: %(
> }

I think I see why it's not working. Essentially, for each element of vec, format is called with only that element as an argument. Essentially, rather than:

    foreach (e; vec)
        writef("%,2?d\t", '_', e);
    writeln();

You get:

    foreach (e; vec)
        writef("%,2?d\t", e);
    writeln();

For whatever reason, it doesn't throw when missing an argument for the separator - I'd say this is a bug (https://issues.dlang.org/show_bug.cgi?id=20541).

For now, you can work around the issue this way:

    import std.stdio : writefln;
    import std.format : format;
    import std.algorithm : map;

    auto vec = [1000, 2000, 3000];

    writefln("%-(%s\t%)", vec.map!(e => format!"%,2?d"('_', e)));

--
  Simen
January 28, 2020
On Tuesday, 28 January 2020 at 08:54:16 UTC, Simen Kjærås wrote:
>     import std.stdio : writefln;
>     import std.format : format;
>     import std.algorithm : map;
>
>     auto vec = [1000, 2000, 3000];
>
>     writefln("%-(%s\t%)", vec.map!(e => format!"%,2?d"('_', e)));
>

That helps, thank you very much.