(We discuss printf early due to its frequent use in examples.)
There have been a number of attempts to match the conciseness and convenience of the C printf() function in the SML setting. All of them suffer by comparison.
The core problem is that C is taking advantage of the type information implicit in the format string, whereas the SML solutions all wind up replicating that type information in the argument expression. No matter how cleverly this is done, it introduces enough syntactic redundancy to make the solution verbose and clumsy.
Mythryl bites the bullet by treating printf (also sprintf and fprintf) as derived forms which are expanded early in the compiler front end into the underlying verbose syntax.
This expansion extracts the implicit type information from the format string, making it visible to the Mythryl typechecker, and thus making the entire construct work with a satisfying lack of visible redundancy.
This solution is a bit of a kludgey hack from a conceptual point of view. For example, aside from complicating the compiler with a special case hack, it means that the format string must be a constant known at compile time for this mechanism to work.
But this hack is an enormous win from a practical point of view, making common text formatting tasks markedly more pleasant:
printf "%g %s %d\n" 1.2 "foo" 32;
The implemented syntax uses curried arguments and thus allows partial application of printf statements, which can occasionally be useful.
The limitation of the form to working only with format-strings known constant at compiler time is not a major restriction in practice. In the rare cases where the format string must be computed at runtime, one can always fall back to the underlying syntax:
sfprintf::printf' (compute_formatstring ()) [ sfprintf::FLOAT 1.2, sfprintf::STRING "foo", sfprintf::INT 32 ];
where compute_formatstring is some user-supplied function.
As always, one may of course dispense with the qualifiers via wholesale importation:
include package sfprintf; printf' (compute_formatstring ()) [ FLOAT 1.2, STRING "foo", INT 32 ];
The same comments apply, mutatis mutandis, to sprintf and fprintf, all of which are ultimately implemented by the sfprintf package, with an assist from src/lib/compiler/front/parser/raw-syntax/printf-format-string-to-raw-syntax.pkg.