The Perils of Format

The Perils of Format
Format is good. Format is bad.

The good is that you can create very nice translatable strings which can deal with reordered parameters, and that perform fairly well.

if Language = Yoda
then fmt := '%1:s apples, %0:d you took.'
else fmt := 'you took %0:d %1:s apples.'; // English
Writeln(Format(fmt, [5, 'green']));

So, what is the pain?  All the checks are done at run time.
Let me repeat that: ... at run time.  

Once again, during a hotfix, I blew it on the parameter type, mistakenly passing a Double into the position where an Integer was expected.

I really wish that there was compiler magic that could validate the type and position of the Format parameters at compile time.  Until there is, I will be careful to send all parameters as strings, and convert to string in the Format argument list - at least for the quick fixes.

#coderant

Comments

  1. Roman Yankovsky This sounds exactly your sort of thing...

    ReplyDelete
  2. Or just ignore the format... In mORMot we use plain % instead of %d or %s or %g and it is sufficient in almost all cases. And also safer (less runtime error) and faster (no need to manually convert to string).

    ReplyDelete
  3. A. Bouchez How is % interpreted - does it change dynamically at runtime depending on the type that's actually passed? How does handle (for example) float formatting flags?

    ReplyDelete
  4. I always wondered, why format doesn't determine the parameter type and simply converts it to string. It already does the checks to be able to generate a meaningful error message, so why not go all the way? I even started to implement this at one time but got sidetracked somehow. Maybe I still have got the sources of that attempt.

    ReplyDelete
  5. Thomas Mueller or pass the parameter to the ToString method or helper for the parameter.

    ReplyDelete
  6. FWIW it's something I added in DWS & is experimental in the Smart JS codegen: constant format strings are type-checked at compile-time.
    It's also something I added to the in-house translation utility, to ensure format strings translations are correct.

    A. Bouchez You need to specify at least the argument index, otherwise it's not translation-friendly.

    Thomas Mueller Jeroen Wiert Pluimers you need all the parameters in the format string for a truly translation-friendly format string, as they may have to be adjusted to locale or specific preferences...

    ReplyDelete
  7. David Millington
    FixInsight has a rule to check Format parameters statically. Though does not work for so complicated case yet.

    ReplyDelete
  8. What about some proper i18n libs, do they exist for Delphi?

    ReplyDelete
  9. Jeroen Wiert Pluimers would be nice, wouldn't it? But unfortunately I can't do that because toString doesn't exist in Delphi 2007. :-( I wish I could upgrade.

    ReplyDelete
  10. I changed all to %s a decade ago.
    But anyway it will blowup when a translator will think it is clever and can shorten the phrase. Obviously with little % characters.
    So I have a function to compare the number of % character occurrences that I must run always after I receive translation.

    ReplyDelete
  11. Cristian PeÈ›a FixInsight checks for that now - see http://sourceoddity.com/fixinsight/doc.html, "W513 Format parameter count mismatch". Could be worth adding to your toolchain, it finds a number of useful things. I rather hope Roman might add more complex Format checking too.

    ReplyDelete
  12. David Millington the translation can be changed at runtime. But yes, FixInsight can help for my mistakes.

    ReplyDelete
  13. David Millington As Roman Yankovsky said W513 works only for simple cases - I've logged last week http://fixinsight.userecho.com/topic/632351-w513-false-positive-when-using-index-specifier/

    ReplyDelete

Post a Comment