Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > d07d7ab417d79053e7e0155c99e1a1c8 > files > 2377

mlton-20100608-3.fc15.i686.rpm

<!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>
      &nbsp;<a href = "TitleIndex">Index</a>
      &nbsp;
</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 =&gt; 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 =&gt; 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 =&gt;
            f (<B><FONT COLOR="#A020F0">fn</FONT></B> p =&gt;
               make (<B><FONT COLOR="#A020F0">fn</FONT></B> s =&gt; 
                     r (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; (p (); TextIO.output (out, s))))))
      <B><FONT COLOR="#A020F0">fun</FONT></B> ` x s = one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f =&gt; f s)
      <B><FONT COLOR="#A020F0">fun</FONT></B> spec to x = one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f =&gt; f o to)
      <B><FONT COLOR="#A020F0">val</FONT></B> B = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; spec Bool.toString z
      <B><FONT COLOR="#A020F0">val</FONT></B> I = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; spec Int.toString z
      <B><FONT COLOR="#A020F0">val</FONT></B> R = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; 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">&quot;Int=&quot;</FONT></B>I`<B><FONT COLOR="#BC8F8F">&quot;  Bool=&quot;</FONT></B>B`<B><FONT COLOR="#BC8F8F">&quot;  Real=&quot;</FONT></B>R`<B><FONT COLOR="#BC8F8F">&quot;\n&quot;</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 &lt;spec1&gt; ... &lt;specn&gt; $ &lt;arg1&gt; ... &lt;argm&gt;
</pre><p>
where each <tt>&lt;speci&gt;</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>&lt;argi&gt;</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 -&gt; bool -&gt; unit = printf `<B><FONT COLOR="#BC8F8F">&quot;Int=&quot;</FONT></B>I`<B><FONT COLOR="#BC8F8F">&quot;  Bool=&quot;</FONT></B>B`<B><FONT COLOR="#BC8F8F">&quot;\n&quot;</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 -&gt; bool -&gt; 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 =&gt; spec Char.toString z
val S = fn z =&gt; spec (fn s =&gt; s) z
</pre><p>
One can define format specifiers for more complex types, e.g. pairs of integers. 
</p>

<pre>val I2 = 
   fn z =&gt; 
   spec (fn (i, j) =&gt; 
         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) =&gt; f (<B><FONT COLOR="#A020F0">fn</FONT></B> p =&gt; p ()) ignore)

      <B><FONT COLOR="#A020F0">val</FONT></B> printf = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; fprintf TextIO.stdOut z

      <B><FONT COLOR="#A020F0">fun</FONT></B> one ((out, f), make) =
         (out, <B><FONT COLOR="#A020F0">fn</FONT></B> r =&gt;
          f (<B><FONT COLOR="#A020F0">fn</FONT></B> p =&gt;
             make (<B><FONT COLOR="#A020F0">fn</FONT></B> s =&gt;
                   r (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; (p (); TextIO.output (out, s))))))
         
      <B><FONT COLOR="#A020F0">val</FONT></B> ` =
         <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; Fold.step1 (<B><FONT COLOR="#A020F0">fn</FONT></B> (s, x) =&gt; one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f =&gt; f s)) z

      <B><FONT COLOR="#A020F0">fun</FONT></B> spec to = Fold.step0 (<B><FONT COLOR="#A020F0">fn</FONT></B> x =&gt; one (x, <B><FONT COLOR="#A020F0">fn</FONT></B> f =&gt; f o to))

      <B><FONT COLOR="#A020F0">val</FONT></B> B = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; spec Bool.toString z
      <B><FONT COLOR="#A020F0">val</FONT></B> I = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; spec Int.toString z
      <B><FONT COLOR="#A020F0">val</FONT></B> R = <B><FONT COLOR="#A020F0">fn</FONT></B> z =&gt; 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 =&gt; 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 =&gt; 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>