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