Announcing as-printf.
Actionscript, as it's name implies, is a high level scripting language. Regardless of what scripting means, it's definitely high level. It has a large core api that shields most programmers from low level manipulation. It's is actually a pretty powerful language, with optional static typing, closures, functions as first class objects and other facilities.
It does, however, has a few key missing features. One of it's noteworthy absences is the low level interface for string manipulation, specially a lack of a printf like facility. [printf] (http://en.wikipedia.org/wiki/Printf) stands for print format, a function that makes mixing strings and variables more convenient. It's surprising really, that actionscript does not have a printf function in it's core library. Even C, which is seen as a low level, unproductive language has it. printf has been around for a long time, and has been known by printf for over 30 years. As far as I can remember, Actionscript and Javascript are the only modern , high level, programming languages that lack such facility.
Printf-as tries to bridge this gap. If you are familiar with printf, the rest of this post will simply bore you. You might just head to the [project's github homepage] (http://http://github.com/arthur-debert/printf-as3/), check out the list of supported formatters or make a fresh svn checkout. The project has a working test suite (I love synchronous re-entrant code) that servers as a good documentation of what to expect. The code license is a MIT License.
Just import br.com.stimuli.string.printf and you are all set.
If you are not sold on what the point is, I'll try to illustrate bellow how it makes things easier.
Advantages: conciseness, readability
At first, it seems the primary advantage is that it's terse and readable. All those quotes and addition signs really get in the way. Suppose you have a class called User, that has a friendly toString output, such as:
1
2
3
|
public function toString() : String{
return "[Class User] name: " + name + ", age:" + age ;
}
|
1
2
3
|
public function toString() : String{
return printf("[Class User] name:%s age: %s", name, age );
}
|
Advantages: helpers, precision, padding
Besides direct substitution, printf can help you format those strings with little fuss. One such helper is the precision formatter. Let's say you have a frame rate counter, that can hold decimal values such as 23.652636. Maybe you wish to truncate the number to a certain digits, for a more friendly output. Just use the dot (".") precision formatter:
1
2
3
|
frate.txt = printf("%.1f fps", frameRate);
// sets the textfield's value to "23.6 fps". The digit 1 after the dot means to
// truncate to 1 decimal place, and the f tells printf to threat it like a float.
|
Or you want to display number in hexadecimal, for example:
1 |
msg = printf("The box color is %h", boxColor); // outputs: The box color is #FF0066
|
Advantages: Logic outside of the string.
Printf can use named variables. Let's say there's an User object, with "name", "middleName" and "lastName" properties.
1 |
msg = "Posted by " + user.name + " " + user.lastName + ".";
|
1 |
msg = "Posted by " + user.lastName + ", " + user.name + ".";
|
1 |
msg = printf( "Posted by %(name)s %(lastName)s", user);
|
1 |
msg = printf( "Posted by %(lastName)s, %(name)s", user);
|
1
2
3
|
...
<string id="greeting">Hello %(firstName)s %(lastName)s</string>
...
|
1 |
msg = printf( "Posted by %(lastName)s, %(name)s", user);
|
1
2
3
|
...
<string id="greeting">Hello %(firstName)s %(middleName)s</string>
...
|
Warning: a loose interpretation of printf
The as-printf implementation is loosely based on python's print and strftime. I did implement most of it's behaviour, but translated freely where it felt that actionscript should behave differently. For example, printf should never raise an error, and if a substitution fails it will be substituted by and empty string.
Warning: performance
While I did not make a consious effort to make as-printf slow, I didn't do any optimizations at all. If you are producing a lot of strings in a place where performance is critical, you'd be better of doing the substitution by hand.
Warning regex implementation
Instead of a full blown parser, I it's a quick hack: a regular expression. That means that making meaningless formats may produce in unexpected results. Mixing formatters that don't go together is a bad idea, be warned.
Wrapping it up:
printf-as is a small, very narrowed focused project. It's a quick hack, but just like bulkloader, it removed a small nag that bothered me when developing in Actionscript.
Thanks to project member Gabriel Laet who fixed bugs, improved the test coverage and convinced me that printf-as should never raise an error.
Happy stringing.
getting a third opinion
Hi,
Looks good. I'll try it.
However I have to correct you, this is not the first incarnation of printf for AS3. AFAIK I've already met two versions:
- de.popforge.utils.sprintf
- http://svn.jimblackler.net/jimblackler/trunk/Flash/BTI/profiler/sprintf.as
But there is one feature I've never seen anywhere: named properties of Objects. That's sweet!!
Thanks :]
Vancura:
Thanks for the correction. At some point, I did see the popforge implementation, but I wanted it to be very python like (named variables, dates and so forth).
The other implementation is novel to me, and it seems to be available for a long time.
Cheers Arthur Debert
Nice!
It would be awesome if printf-as3 would support the n$ notation (POSIX extension). It is essential for properly implementing GetText:
http://en.wikipedia.org/wiki/Printf#printf_format_placeholders
In fact i have already implemented printf in as3 with this in place (including GetText which uses industry standard .po files), but my printf implementation unfortunately lacks in other areas.
Have the last word