On 2013-05-04 01:28:43, Huon Wilson wrote: > 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 > _______________________________________________
Hi All, Me and dbaupp have done some preliminary implementation[1] on the formatting side of things. During discussion on IRC we have come up with a few extra details that should probably be mentioned. Using a writer for format strings is useful for efficiency, especially when doing things like writing to the terminal or a file. So there are 3 syntax extensions that would be used in order to make this work and be nice: * fmt! which is essentially the same as now, returns a ~str * printf! which writes straight to stdout (effectively replacing `io::print(fmt!(...))`) * writef! which would take an io::Writer as it's first argument fmt! and printf! would simply be written in terms of writef! with pre-supplied Writers. The actual format string has, unsurprisingly, created a lot of discussion mostly around it's relative power. The current placeholder format is as follows: % position flags width precision numeric_arg conversion_specifier With all except the '%' and conversion specifier being optional. The specific format of the fields is detailed in the string parser. Currently we have identified 4 conversion specifiers: 'd', 'f', 's' and '?'. These are interpreted as "convert as" specifiers so '%d' means "convert this argument as a number" and the argument type itself knows how to do this. For flags, we have '0', '-', '=', ' ', '+' and '\'' which have the same meaning as standard printf (where they exist in standard printf). * '0' means zero-pad * '-' means left-justified in the field * '=' means center in the field * ' ' means that a blank should always be before a signed number * '+' means that a '-' or '+' should always be placed before a signed number Width and precision fields are similar to the standard printf fields, just with minor syntax changes in the case of using the next or a specific argument. The numeric arg field is formatted like this: `<[0-9]+>` and is used for supplying a base to 'd' conversions, with the default being 10. This means that '%x', '%o' and '%t' can all be replaced with this format: '%<16>d', '%<8>d' and '%<2>d'. You could obviously specify other bases to print in up to 36. I'm in favor of keeping printf-style strings. For one, they are what we already have, so in that sense it's merely not changing that. Also, I am struggling to see the objective advantages of other implementations, while they aren't worse, I don't see a reason to use them over what we alrady have. Many people want more power in the format strings, but I am reluctant to include it for a couple reasons. * Turning format specifiers into a mini-language (more than it already is) seems to add too much complexity for not enough return. In practice I have rarely seen many of the complex features of other formatting systems be used, since they are often too simplistic for many cases, or the resulting string is too complex to be clear any more. This is the issue with regex, but without the advantages that regex gives you. * Adding more power is the perfect way to introduce undefined or unspecified behaviour. It forces the definition of further syntax rules and then limitations. Eventually you either end up with something that is so complex nobody uses it, or so ham-strung that it isn't worth using. I would much rather spend time implementing common features that are likely to be used (centering for example) than obscure features that only look good in examples. So that's my update and opinion. -- James Miller [1]: https://github.com/Aatch/rust-fmt _______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev