2009/11/30 Baojian Hua <span dir="ltr">&lt;<a href="mailto:huabj@mail.ustc.edu.cn">huabj@mail.ustc.edu.cn</a>&gt;</span><br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
We&#39;ve been useing MLton for over 7 years for our research<br>
projects, and recently we&#39;re planning to read and hack some source<br>
code of MLton (and hopefully we can contribute in the<br>
future).<br></blockquote><div><br>It would be great if you could add a link to your project(s) to <a href="http://mlton.org/Users">http://mlton.org/Users</a>.<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

And we start by reading sources in &quot;lib/mlton/basic/&quot;, but<br>
the documentation is rare, so we have to send some questions here:<br>
in files &quot;layout.sig, sml&quot;, this data structure:<br>
<br>
datatype t = T of {length: int,<br>
                   tree: tree}<br>
and tree =<br>
   Empty<br>
  | String of string<br>
  | Sequence of t list<br>
  | Align of {force: bool, rows: t list}<br>
  | Indent of t * int<br>
<br>
Does the &quot;force&quot; mean we must align several line?</blockquote><div><br>Looking at layout.sig, the comments note:<br><br>      (* layout the objects on separate lines*)<br>      val align: t list -&gt; t<br>      (* layout the objects on separate lines, if necessary *)<br>
      val mayAlign: t list -&gt; t<br><br>where, &quot;align&quot; corresponds to &quot;Align {force = true, ...}&quot; and &quot;mayAlign&quot; corresponds to &quot;Align {force = false, ...}&quot;.<br>So, &quot;force = true&quot; requires that each element be printed and aligned on a separate line.<br>
 </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> And in calculating<br>
the length, I&#39;d expect to see this:<br>
<br>
case tree<br>
 of Align {rows, ...} =&gt; max (rows)  (* the longest one *)<br>
  | _ =&gt;<br>
<br>
but the code is this:<br>
<br>
case tree<br>
 of Align {rows, ...} =&gt; \Sigma (rows)  (* the whole *)<br>
  | _ =&gt;<br></blockquote><div><br>The &quot;length&quot; field is really a &quot;size&quot; measure.  That is, it measures the total size of all the string elements in the layout (+1 for each space that will appear between Align elements).  It does not measure the length of a line of the layout; note, for example, that &quot;length&quot; is not incremented on an Indent.<br>
<br>Looking at the &quot;print&quot; function (layout.sml:122) and the &quot;Align&quot; case (layout.sml:168), you see that the length is ignored when force == true; in that case, each layout element is printed on a separate line.  When force == false, the length is used to determine if all of the layout elements can be printed on the same line.<br>
<br>One subtlety is that if one does:<br>  val lay = mayAlign [align [str &quot;A&quot;, str &quot;B&quot;], align [str &quot;C&quot;, str &quot;D&quot;]]<br>  val () = print (lay, TextIO.print)<br>then you will get the output:<br>
A B C D<br>Note that the &quot;force = true&quot; on the inner aligns is ignored, because the outer align put all of its inner layout elements on to one line.<br><br>Hope that helps.<br><br></div></div>