Poll on improved format strings.

renoX renosky at free.fr
Wed Mar 7 22:21:22 PST 2007


Daniel Keep a écrit :
> 
> renoX wrote:
>> Daniel Keep Wrote:
>>> To be honest, I think the type suffix needs to go.  After all, if you
>>> know what the type is at compile-time, why do I need to repeat it?
>> If the compatibility with printf(allowing %d without {...} format string) is removed (and I think I'll do this) then %{var} would be also allowed.
>>
>>> Of course, doing that leaves you with the problem of how to specify
>>> formatting options... but then in the majority of cases, you probably
>>> don't care; you just want the thing output.
>>>
>>> So how about something like this:
>>>
>>> Expansion ::= "$" ExpansionSpec
>>>
>>> ExpansionSpec ::= FormattingOptions ExpansionExpr
>>> ExpansionSpec ::= ExpansionExpr
>>>
>>> FormattingOptions ::= "(" string ")"
>>>
>>> ExpansionExpr ::= "{" D_Expression "}"
>>> ExpansionExpr ::= D_Identifier
>>>
>>> So the example above becomes "... $(08){var1+var2} ...": one character
>>> longer, but gives you more freedom as to what you can put in the
>>> formatting options.  Plus, if you don't care how it's formatted, you can
>>> use "... ${var1+var2} ...", and if you just want to print a variable
>>> out, you can use "... $somevar ...".
>> Printf-Format string are quite powerful, and they're well known so I think their syntax should be kept, just with the obligation to follow by {...}: so the following would work:
>> %{var}, %08X{var}, etc.. (%d{var} and %s{var} wouldn't be useful anymore, I agree but to avoid surprising C programmers, they should be kept).
> 
> (What, and having type inference, templates, aa's, compile-time function
> evaluation, et al. isn't going to surprise them?! :P  This is
> incidentally WHY I picked "$": so that they don't think "Hey; this is a
> printf format string!)
>> $somevar or %somevar without {...}, I don't know, it's shorter, sure but less readable I think.
> 
> I'm sure bash and PHP programmers would disagree with you. :P  I chose
> the syntax precisely because there are languages out there that do the
> *exact* same thing: the only thing that's new is the (opt) part.

Note that in Ruby, a scripting language also the syntax is 
"...#{<var>}..." of course there were some requests to allow #var but so 
far Matz has rejected them (I think, I don't follow Ruby closely).

> You want to cater to C programmers, and that's fine; I'm more interested
> in coming from a different angle (mostly because I like how these look).

Well currently D is using C-style format strings, so I'm not sure what 
the gain would be to change the syntax.

>>> Plus, if you discount the formatting stuff out the front, it's roughly
>>> comparable to how variable expansions are written in bash and the like.
>>>  I also think that Nemerle (which has had this sort of compile-time
>>> printf stuff for ages) does it the same way.
>>>
>>> As for the spec itself: it should be const char[] only, and display a
>>> meaningful error if the programmer tries to pass a non-const char[].
>> For the const char[] only, I agree.
>> The problem for the 'meaningful error' is that D doesn't provide a way to print the line number of where the template was called..
> 
> A trick might be to use a... hmm...  I wonder, if your function
> returned, say "static assert(false, \"Ruh-rho!\")" to the mixin(...)
> keyword, which line would the compiler say it was on? :P

Interesting suggestion. I'll try it.

>>> That said, I think you should also provide a "run-time" version of the
>>> function that has the exact same parser, formatting, etc., but the user
>>> can pass one or more hash maps to the function.  This would allow people
>>> to use the same format for both compile and runtime, whilst not making
>>> the runtime version a security risk (well, aside from arbitrary
>>> expressions, anyway).  For example:
>>>
>>>> auto author = "renoX";
>>>> auto d_bdfl = "Walter Bright";
>>>> auto life = 42;
>>>>
>>>> mixin(swritefln("Author: $author, BDFL: $(q)d_bdfl, "
>>>>     "Meaning of life: $life"));
>>>>
>>>> // Author: renoX, BDFL: "Walter Bright", Meaning of life: 42
>>>>
>>>> char[][char[]] strings;
>>>> int[char[]] ints;
>>>>
>>>> strings["author"] = author;
>>>> strings["d-bdfl"] = d_bdfl;
>>>> ints["life"] = life;
>>>>
>>>> auto formatstr = "Author: $author, BDFL: $(q){d-bdfl}, "
>>>>     "Meaning of life: $life";
>>>>
>>>> writefln(formatstr, strings, ints);
>>>>
>>>> // Prints the same thing as above
>> Python has this string manipulation possibility with the associative array, I think.
>> What is supposed to happen if one key belongs to several associative arrays? Or if it doesn't exist in all the associative arrays provided?
> 
> For the first, it simply uses the first one it finds.  Actually, this
> design is bad because of the multiple aa thing, but I only did that
> because Python is dynamically typed.  And there are cases where being
> able to dump multiple types into a format string is very handy.
> 
> For the second, it's clearly a run-time error; throw an exception.
> 
> One possible alternative is to have a slightly different version which
> will only fill in the fields it can, and leave the others.
> 
>>> 	-- Daniel
>>>
>>> P.S.  $(q){...} is stolen from Lua's "%q" format specifier: prints a
>>> string out complete with escaping and quotation marks :P
>> I don't understand the difference between %q and %s.
>>
>> Regards,
>> renoX
> 
> auto msg = "This is a \"string\".\n\tIt has some escaped characters.";
> 
>> writefln("$(q)msg", msg);
>> writefln("$(s)msg", msg);
> 
> Produces:
> 
>> This is a "string".
>>         It has some escaped characters.
>> "This is a \"string\".\n\tIt has some escaped characters."
> 
> This is, admittedly, more useful in Lua which has an eval function :P
> 
> 	-- Daniel

OK, thanks for the information.
renoX





More information about the Digitalmars-d mailing list