<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta name="robots" content="index,nofollow"> <title>Printf - MLton Standard ML Compiler (SML Compiler)</title> <link rel="stylesheet" type="text/css" charset="iso-8859-1" media="all" href="common.css"> <link rel="stylesheet" type="text/css" charset="iso-8859-1" media="screen" href="screen.css"> <link rel="stylesheet" type="text/css" charset="iso-8859-1" media="print" href="print.css"> <link rel="Start" href="Home"> <link rel="Appendix" title="printf.sml" href="http://mlton.org/pages/Printf/attachments/printf.sml"> </head> <body lang="en" dir="ltr"> <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-833377-1"; urchinTracker(); </script> <table bgcolor = lightblue cellspacing = 0 style = "border: 0px;" width = 100%> <tr> <td style = " border: 0px; color: darkblue; font-size: 150%; text-align: left;"> <a class = mltona href="Home">MLton MLTONWIKIVERSION</a> <td style = " border: 0px; font-size: 150%; text-align: center; width: 50%;"> Printf <td style = " border: 0px; text-align: right;"> <table cellspacing = 0 style = "border: 0px"> <tr style = "vertical-align: middle;"> </table> <tr style = "background-color: white;"> <td colspan = 3 style = " border: 0px; font-size:70%; text-align: right;"> <a href = "Home">Home</a> <a href = "TitleIndex">Index</a> </table> <div id="content" lang="en" dir="ltr"> Programmers coming from C or Java often ask if <a href="StandardML">Standard ML</a> has a <tt>printf</tt> function. It does not. However, it is possible to implement your own version with only a few lines of code. <p> Here is a definition for <tt>printf</tt> and <tt>fprintf</tt>, along with format specifiers for booleans, integers, and reals. </p> <pre class=code> <B><FONT COLOR="#0000FF">structure</FONT></B> Printf = <B><FONT COLOR="#0000FF">struct</FONT></B> <B><FONT COLOR="#A020F0">fun</FONT></B> $ (_, f) = f (<B><FONT COLOR="#A020F0">fn</FONT></B> p => p ()) ignore <B><FONT COLOR="#A020F0">fun</FONT></B> fprintf out f = f (out, id) <B><FONT COLOR="#A020F0">val</FONT></B> printf = <B><FONT COLOR="#A020F0">fn</FONT></B> z => fprintf TextIO.stdOut z <B><FONT COLOR="#A020F0">fun</FONT></B> one ((out, f), make) g = g (out, <B><FONT COLOR="#A020F0">fn</FONT></B> r => f (<B><FONT COLOR="#A020F0">fn</FONT></B> p => make (<B><FONT COLOR="#A020F0">fn</FONT></B> s => r (<B><FONT COLOR="#A020F0">fn</FONT></B> () => (p (); TextIO.output (out, s)))))) <B><FONT COLOR="#A020F0">fun</FONT></B> ` x s = one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f => f s) <B><FONT COLOR="#A020F0">fun</FONT></B> spec to x = one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f => f o to) <B><FONT COLOR="#A020F0">val</FONT></B> B = <B><FONT COLOR="#A020F0">fn</FONT></B> z => spec Bool.toString z <B><FONT COLOR="#A020F0">val</FONT></B> I = <B><FONT COLOR="#A020F0">fn</FONT></B> z => spec Int.toString z <B><FONT COLOR="#A020F0">val</FONT></B> R = <B><FONT COLOR="#A020F0">fn</FONT></B> z => spec Real.toString z <B><FONT COLOR="#0000FF">end</FONT></B> </PRE> <p> </p> <p> Here's an example use. </p> <pre class=code> <B><FONT COLOR="#A020F0">val</FONT></B> () = printf `<B><FONT COLOR="#BC8F8F">"Int="</FONT></B>I`<B><FONT COLOR="#BC8F8F">" Bool="</FONT></B>B`<B><FONT COLOR="#BC8F8F">" Real="</FONT></B>R`<B><FONT COLOR="#BC8F8F">"\n"</FONT></B> $ <B><FONT COLOR="#5F9EA0">1</FONT></B> false <B><FONT COLOR="#5F9EA0">2.0</FONT></B> </PRE> <p> </p> <p> This prints the following. <pre>Int=1 Bool=false Real=2.0 </pre> </p> <p> In general, a use of <tt>printf</tt> looks like </p> <pre>printf <spec1> ... <specn> $ <arg1> ... <argm> </pre><p> where each <tt><speci></tt> is either a specifier like <tt>B</tt>, <tt>I</tt>, or <tt>R</tt>, or is an inline string, like <tt>`"foo"</tt>. A backtick (<tt>`</tt>) must precede each inline string. Each <tt><argi></tt> must be of the appropriate type for the corresponding specifier. </p> <p> SML <tt>printf</tt> is more powerful than its C counterpart in a number of ways. In particular, the function produced by <tt>printf</tt> is a perfectly ordinary SML function, and can be passed around, used multiple times, etc. For example: </p> <pre class=code> <B><FONT COLOR="#A020F0">val</FONT></B> f: int -> bool -> unit = printf `<B><FONT COLOR="#BC8F8F">"Int="</FONT></B>I`<B><FONT COLOR="#BC8F8F">" Bool="</FONT></B>B`<B><FONT COLOR="#BC8F8F">"\n"</FONT></B> $ <B><FONT COLOR="#A020F0">val</FONT></B> () = f <B><FONT COLOR="#5F9EA0">1</FONT></B> true <B><FONT COLOR="#A020F0">val</FONT></B> () = f <B><FONT COLOR="#5F9EA0">2</FONT></B> false </PRE> <p> </p> <p> The definition of <tt>printf</tt> is even careful to not print anything until it is fully applied. So, examples like the following will work as expected. </p> <pre>val f: int -> bool -> unit = printf `"Int="I`" Bool="B`"\n" $ 13 val () = f true val () = f false </pre><p> It is also easy to define new format specifiers. For example, suppose we wanted format specifiers for characters and strings. </p> <pre>val C = fn z => spec Char.toString z val S = fn z => spec (fn s => s) z </pre><p> One can define format specifiers for more complex types, e.g. pairs of integers. </p> <pre>val I2 = fn z => spec (fn (i, j) => concat ["(", Int.toString i, ", ", Int.toString j, ")"]) z </pre><p> Here's an example use. </p> <pre>val () = printf `"Test "I2`" a string "S`"\n" $ (1, 2) "hello" </pre><h2 id="head-61fc0a9cf6f322aec07bfaef46205ce788f00071">Printf via fold</h2> <p> Printf is best viewed as a special case of variable-argument <a href="Fold">Fold</a> that inductively builds a function as it processes its arguments. Here is the definition of a <tt>Printf</tt> structure in terms of fold. The structure is equivalent to the above one, except that it uses the standard <tt>$</tt> instead of a specialized one. </p> <pre class=code> <B><FONT COLOR="#0000FF">structure</FONT></B> Printf = <B><FONT COLOR="#0000FF">struct</FONT></B> <B><FONT COLOR="#A020F0">fun</FONT></B> fprintf out = Fold.fold ((out, id), <B><FONT COLOR="#A020F0">fn</FONT></B> (_, f) => f (<B><FONT COLOR="#A020F0">fn</FONT></B> p => p ()) ignore) <B><FONT COLOR="#A020F0">val</FONT></B> printf = <B><FONT COLOR="#A020F0">fn</FONT></B> z => fprintf TextIO.stdOut z <B><FONT COLOR="#A020F0">fun</FONT></B> one ((out, f), make) = (out, <B><FONT COLOR="#A020F0">fn</FONT></B> r => f (<B><FONT COLOR="#A020F0">fn</FONT></B> p => make (<B><FONT COLOR="#A020F0">fn</FONT></B> s => r (<B><FONT COLOR="#A020F0">fn</FONT></B> () => (p (); TextIO.output (out, s)))))) <B><FONT COLOR="#A020F0">val</FONT></B> ` = <B><FONT COLOR="#A020F0">fn</FONT></B> z => Fold.step1 (<B><FONT COLOR="#A020F0">fn</FONT></B> (s, x) => one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f => f s)) z <B><FONT COLOR="#A020F0">fun</FONT></B> spec to = Fold.step0 (<B><FONT COLOR="#A020F0">fn</FONT></B> x => one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f => f o to)) <B><FONT COLOR="#A020F0">val</FONT></B> B = <B><FONT COLOR="#A020F0">fn</FONT></B> z => spec Bool.toString z <B><FONT COLOR="#A020F0">val</FONT></B> I = <B><FONT COLOR="#A020F0">fn</FONT></B> z => spec Int.toString z <B><FONT COLOR="#A020F0">val</FONT></B> R = <B><FONT COLOR="#A020F0">fn</FONT></B> z => spec Real.toString z <B><FONT COLOR="#0000FF">end</FONT></B> </PRE> <p> </p> <p> Viewing <tt>printf</tt> as a fold opens up a number of possibilities. For example, one can name parts of format strings using the fold idiom for naming sequences of steps. </p> <pre>val IB = fn u => Fold.fold u `"Int="I`" Bool="B val () = printf IB`" "IB`"\n" $ 1 true 3 false </pre><p> One can even parametrize over partial format strings. </p> <pre>fun XB X = fn u => Fold.fold u `"X="X`" Bool="B val () = printf (XB I)`" "(XB R)`"\n" $ 1 true 2.0 false </pre><h2 id="head-a4bc8bf5caf54b18cea9f58e83dd4acb488deb17">Also see</h2> <ul> <li> <p> <a href="PrintfGentle">PrintfGentle</a> </p> </li> <li> <p> <a href = "References#Danvy98"> Functional Unparsing</a> </p> </li> </ul> </div> <p> <hr> Last edited on 2007-08-15 22:07:07 by <span title="fenrir.uchicago.edu"><a href="MatthewFluet">MatthewFluet</a></span>. </body></html>