A proposal to add String.prototype.format

Shanjian Li shanjian at google.com
Wed Mar 9 10:20:34 PST 2011

Comment inline.

On Wed, Mar 9, 2011 at 12:37 AM, Lasse Reichstein <
reichsteinatwork at gmail.com> wrote:

> On Wed, 09 Mar 2011 01:21:09 +0100, Shanjian Li <shanjian at google.com>
> wrote:
>  http://wiki.ecmascript.org/doku.php?id=strawman:string_format_take_two
>> Please kindly review the proposal and let me know your feedback.
> Just some nitpciking:
> It doesn't specify how to print objects, except for %s, which says that if
> the argument is not
> a string, convert it to string using .toString().

If the format specifier does not apply to the argument given, it should
raise exceptions. Except string conversion, no other conversion will be

> The string conversion should probably use the internal ToString function
> instead (which works for null
> and undefined too).


> For formats expecting numbers, it should convert the argument to a number
> using ToNumber.

Probably not. As string is the thing being constructed, it make sense to
offer "hidden" string conversion. In my experience using this feature in
Python, it is within expectation and offer some convenience. Any further
"hidden" conversion should really be avoided.

> Rounding is specified as "math.round(n - 0.5)" (capital M in Math?).

Right, thanks.

> This leaves it open whether overwriting Math.round should change the
> behavior of format. It probably
> shouldn't (i.e., again it would be better to specify in terms of internal,
> non-use-modifiable functions).


> The rounding is equivalent to Math.floor(n) (aka round towards -Infinity),
> if I'm not mistaken, so why
> not just use that?

In this example, 8 / (3 - 8 / 3) , the display will be 23.99999999999999. So
the internal representation could be a little bit more or a little bit less
than the theoretical value due to float precision. Math.round might generate
less surprise results than Math.floor.  Of cause, the internal
implementation shouldn't rely on either of these two.

> (Personally I would prefer truncation (round towards zero), if conversion
> to integer is necessary).
> Why can octal, binary and hexidecimal forms only be used on integers?
> Number.prototype.toString with
> an argument works on fractions too (try Math.PI.toString(13) for laughs :).

> Why only fixed bases (2,8,10,16)? How about adding an optional base
> parameter to number display (with
> x, d, o, b as shorthands for the more standard bases)? Again,
> Number.prototype.toString means that it's
> already in the language. (I know that step 7 says copy the format of other
> languages, but that seems
> shortsighted since ECMAScript is not those languages, and only copying
> functionality from C verbatim
> seems like tying your shoelaces together before the race).
> The question for both questions is how useful is that. If it is only needed
in one or few rare occasions, it is probably not a good idea to complicate
the language.

> "Placeholder used in format specifier part can not have format specifier.
> This prevent the replacement
> from embedding more than one level."
> Should that be "... can not have a placeholder."?
No.   The former prevent any format specifier (including embedded
placeholder). Refer to the Python specification, it does make sense.

> If the placeholder value is not a string, it should be converted to a
> string.
> If it is not a valid format, what happens then?

Raise exception?

> Is the following valid:
>  "{x} and {1[y]}".format({x:42},{y:37})
> I.e., can object property shorthands ({x} instead of {0[x]}) be used if
> there are more than one argument?

Good points. Possible choices:
1. {x} always refer to the first object given.
2. {x} only works when there is one and only one object argument.
3. {x} will be replaced by the first object that has property x, ie. the
following should work too.
    "{x}, {z} and {1[y]}".format({x:42}, {z:43, y:37})

I prefer 1.

> And some arbitrary ideas for extension:
> How about a boolean test that checks for falsy-ness of the argument and
> acts as one of two other
> formats or literals?
> E.g.
>  "{0:s} drew {1:?his|her} gun.".format(person.name, person.isMale)
>  "Please press return{0:?.|{1}}".format(notCritical, " and run!")

Interesting. In example 1, the issue is literal get into the placeholder,
that could make things messy.

> Or allow computed indices?
>  "{0[{1}][he]} drew {0[{1}][his]} gun.".format({male:{he:"He",his:"his"},
> female:{he:"She",his:"her"}}, "female");

Allow embedded placeholder inside the field part (not the format specifier
part) of a placeholder is something that I will be very cautious about.


> /L
> --
> Lasse Reichstein - reichsteinatwork at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110309/a84e22fc/attachment.html>

More information about the es-discuss mailing list