Hi all,

Aatch, Kimundi and I (and maybe some others... sorry if I've forgotten
you) came up with a bit of proposal on IRC for handling fmt!. It's
possibly been considered already, but whatever, we'd like some
comments on it.


There would one trait for each format specifier (probably excluding
`?'), e.g. FormatC for %c, FormatD for %d/%i, FormatF for %f, and
format would just require that the value for each format specifier
implements the correct trait. (Presumably this check can be done
"automatically" by attempting to call the appropriate method and
using the type checker.)

In code,


trait FormatC {
  fn format_c(&self, w: &Writer, flags: Flags);
}

impl FormatC for char {
  fn format_c(&self, w: &Writer, _: Flags) { w.write_char(*self) }
}

struct MyChar(char);
impl FormatC for MyChar {
  fn format_c(&self, w: &Writer, _: Flags) { w.write_char(**self) }
}

fmt!("%c%c%c", 'a', MyChar('a'), ~"str")

// becomes

'a'.format_c(w, {});
MyChar('a').format_c(w, {});
~"str".format_c(w, {});


And the first two would resolve/type-check fine, but the last would
not. (`Flags' would contain the width and precision specifiers and all
that.)


This could then be extended to have a dynamic formatter, which allows
types to format for any specifier at runtime (i.e. get around compile
time restrictions). Our thoughts were to add an extra flag to indicate
this (e.g. !), so that it is entirely and explicitly opt-in. (Similar
to Python's __format__ and Go's fmt (I think).)


trait DynamicFormat {
  fn format_dynamic(&self, w: &Writer, spec: FormatSpec);
}

fmt!("%!s %!10.3f", a, b)

// becomes

a.format_dynamic(w, {flags: {}, type: 's'});
w.write_str(" ");
b.format_dynamic(w, {flags: {width: 10, prec: 3}, type: 'f'});


(Presumably this could also have a lint mode, to give an error or
warning if dynamic formatting is used.)


There were also some other discussions about the fmt! syntax, e.g. it
was suggested that the following could be equivalent to each other

fmt!("%{2}[0].[1]f %{2}e", 10, 3, 1.01);
fmt!("%10.3f %e", 1.01, 1.01);

This is an explicit divergence from printf's slightly archane */'n$'
placeholder syntax. One could use `[*]`  to just refer to the next
argument, like * does by default. (Aatch has a format spec parser[1]
in the works that supports this syntax.)


Huon

[1]: https://gist.github.com/Aatch/fb94960ab770c7df5718
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to