<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hello,</div><div><br></div><div>Here is the latest Caml Weekly News, for the week of July 8 to 15, 2008.</div><div><br></div><div>1) New library: Easy-format 0.9.0</div><div>2) Troublesome nodes</div><div>3) Name of currently executing function</div><div><br></div><div>========================================================================</div><div>1) New library: Easy-format 0.9.0</div><div>Archive: <<a href="http://groups.google.com/group/fa.caml/browse_thread/thread/61252c85858fe7ea#">http://groups.google.com/group/fa.caml/browse_thread/thread/61252c85858fe7ea#</a>></div><div>------------------------------------------------------------------------</div><div>** Martin Jambon announced:</div><div><br></div><div>I would like to announce a small library (a module in fact) that is meant to</div><div>make it easy to produce pretty-printed text:</div><div><br></div><div> <<a href="http://martin.jambon.free.fr/easy-format.html">http://martin.jambon.free.fr/easy-format.html</a>></div><div><br></div><div>The data to be printed goes through a tree that carries all the information</div><div>required for pretty-printing. After that, a single call to</div><div>Easy_format.Pretty.to_stdout (for instance) outputs the indented result.</div><div><br></div><div>There's a reasonably complete example at</div><div><br></div><div> <<a href="http://martin.jambon.free.fr/easy_format_example.html">http://martin.jambon.free.fr/easy_format_example.html</a>></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** He later added:</div><div><br></div><div>I've just released a richer version of Easy-format.</div><div>The main URL is still <<a href="http://martin.jambon.free.fr/easy-format.html">http://martin.jambon.free.fr/easy-format.html</a>></div><div><br></div><div>It now offers the following additional features:</div><div><br></div><div>- Support for separators that stick to the next list item (e.g. "|")</div><div>- More wrapping options</div><div>- Added Custom kind of nodes for using Format directly or existing</div><div> pretty-printers</div><div>- Support for markup and escaping, allowing to produce colorized output</div><div> (HTML, terminal, ...) without interfering with the computation of</div><div> line breaks and spacing.</div><div><br></div><div>Easy-format now takes advantage of most features of the Format module, with</div><div>the notable exception of tabulation boxes. I'd be curious so see any</div><div>interesting use of tabulation boxes.</div><div><br></div><div><br></div><div>This release has slight incompatibilities with version 0.9.0 which was</div><div>released earlier this week, simply because more options were added:</div><div><br></div><div>- Deprecated use of Easy_format.Param. Instead, inherit from</div><div> Easy_format.list,</div><div> Easy_format.label or Easy_format.atom.</div><div>- Atom nodes have now one additional argument for parameters.</div><div>- All record types have been extended with more fields.</div><div> Using the "with" mechanism for inheritance is the best way of limiting</div><div> future incompatibilities.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>2) Troublesome nodes</div><div>Archive: <<a href="http://groups.google.com/group/fa.caml/browse_thread/thread/943eb2043c8c1266#">http://groups.google.com/group/fa.caml/browse_thread/thread/943eb2043c8c1266#</a>></div><div>------------------------------------------------------------------------</div><div>** Deep in this thread, Dario Teixeira said:</div><div><br></div><div>For the sake of future reference, I'm going to summarise the solution to</div><div>the original problem, arrived at thanks to the contribution of various</div><div>people in this list (your help was very much appreciated!). This might</div><div>came in handy in the future if you run into a similar problem.</div><div><br></div><div>So, we have a document composed of a sequence of nodes. There are four</div><div>different kinds of nodes, two of which are terminals (Text and See)</div><div>and two of which are defined recursively (Bold and Mref). Both See and</div><div>Mref produce links, and we want to impose a constraint that no link node</div><div>shall be the immediate ancestor of another link node. An additional</div><div>constraint is that nodes must be created via constructor functions.</div><div>Finally, the structure should be pattern-matchable, and the distinction</div><div>between link/nonlink nodes should be preserved so that Node-to-Node</div><div>functions do not require code duplication and/or ugly hacks.</div><div><br></div><div>Using conventional variants, the structure can be represented as follows.</div><div>Alas, this solution is not compatible with constructor functions and</div><div>requires unwanted scaffolding:</div><div><br></div><div>module Ast =</div><div>struct</div><div> type super_node_t =</div><div> | Nonlink_node of nonlink_node_t</div><div> | Link_node of link_node_t</div><div> and nonlink_node_t =</div><div> | Text of string</div><div> | Bold of super_node_t list</div><div> and link_node_t =</div><div> | Mref of string * nonlink_node_t list</div><div> | See of string</div><div>end</div><div><br></div><div><br></div><div>Below is the solution that was finally obtained. Nodes are represented</div><div>using polymorphic variants, and the module itself is recursive to get</div><div>around the "type not fully defined" problem:</div><div><br></div><div>module rec Node:</div><div>sig</div><div> type nonlink_node_t = [ `Text of string | `Bold of Node.super_node_t list ]</div><div> type link_node_t = [ `See of string | `Mref of string * nonlink_node_t list ]</div><div> type super_node_t = [ nonlink_node_t | link_node_t ]</div><div><br></div><div> val text: string -> nonlink_node_t</div><div> val bold: [< super_node_t] list -> nonlink_node_t</div><div> val see: string -> link_node_t</div><div> val mref: string -> nonlink_node_t list -> link_node_t</div><div>end =</div><div>struct</div><div> type nonlink_node_t = [ `Text of string | `Bold of Node.super_node_t list ]</div><div> type link_node_t = [ `See of string | `Mref of string * nonlink_node_t list ]</div><div> type super_node_t = [ nonlink_node_t | link_node_t ]</div><div><br></div><div> let text txt = `Text txt</div><div> let bold seq = `Bold (seq :> super_node_t list)</div><div> let see ref = `See ref</div><div> let mref ref seq = `Mref (ref, seq)</div><div>end</div><div><br></div><div><br></div><div>If you try it out, you will see that this solution enforces the basic</div><div>node constraints. The values foo1-foo4 are valid, whereas the compiler</div><div>won't accept foo5, because a link node is the parent of another:</div><div><br></div><div>open Node</div><div>let foo1 = text "foo"</div><div>let foo2 = bold [text "foo"]</div><div>let foo3 = mref "ref" [foo1; foo2]</div><div>let foo4 = mref "ref" [bold [see "ref"]]</div><div>let foo5 = mref "ref" [see "ref"]</div><div><br></div><div><br></div><div>Now, suppose you need to create an Ast-to-Node sets of functions (a likely</div><div>scenario if you are building a parser for documents). The solution is</div><div>fairly straightforward, but note the need to use the cast operator :></div><div>to promote link/nonlink nodes to supernodes:</div><div><br></div><div>module Ast_to_Node =</div><div>struct</div><div> let rec convert_nonlink_node = function</div><div> | Ast.Text txt -> Node.text txt</div><div> | Ast.Bold seq -> Node.bold (List.map convert_super_node seq)</div><div><br></div><div> and convert_link_node = function</div><div> | Ast.Mref (ref, seq) -> Node.mref ref (List.map convert_nonlink_node seq)</div><div> | Ast.See ref -> Node.see ref</div><div><br></div><div> and convert_super_node = function</div><div> | Ast.Nonlink_node node -> (convert_nonlink_node node :> Node.super_node_t)</div><div> | Ast.Link_node node -> (convert_link_node node :> Node.super_node_t)</div><div>end</div><div><br></div><div><br></div><div>Finally, another common situation is to build functions to process nodes.</div><div>The example below is that of a node-to-node "identity" module. Again, it</div><div>is fairly straightforward, but note the use of the operator # and the need</div><div>to cast link/nonlink nodes to supernodes:</div><div><br></div><div>module Node_to_Node =</div><div>struct</div><div> open Node</div><div><br></div><div> let rec convert_nonlink_node = function</div><div> | `Text txt -> text txt</div><div> | `Bold seq -> bold (List.map convert_super_node seq)</div><div><br></div><div> and convert_link_node = function</div><div> | `See ref -> see ref</div><div> | `Mref (ref, seq) -> mref ref (List.map convert_nonlink_node seq)</div><div><br></div><div> and convert_super_node = function</div><div> | #nonlink_node_t as node -> (convert_nonlink_node node :> super_node_t)</div><div> | #link_node_t as node -> (convert_link_node node :> super_node_t)</div><div>end</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** He later added:</div><div><br></div><div>Sorry, but in the meantime I came across two problems with the supposedly</div><div>ultimate solution I just posted. I have a correction for one, but not</div><div>for the other.</div><div><br></div><div>The following statements trigger the first problem:</div><div><br></div><div>let foo1 = text "foo"</div><div>let foo2 = see "ref"</div><div>let foo3 = bold [foo1; foo2]</div><div><br></div><div>Error: This expression has type Node.link_node_t but is here used with type</div><div> Node.nonlink_node_t</div><div> These two variant types have no intersection</div><div><br></div><div>The solution that immediately comes to mind is to make the return types</div><div>for the constructor functions open: (I can see no disadvantage with</div><div>this solution; please tell me if you find any)</div><div><br></div><div><br></div><div>module rec Node:</div><div>sig</div><div> type nonlink_node_t = [ `Text of string | `Bold of Node.super_node_t list ]</div><div> type link_node_t = [ `See of string | `Mref of string * nonlink_node_t list ]</div><div> type super_node_t = [ nonlink_node_t | link_node_t ]</div><div><br></div><div> val text: string -> [> nonlink_node_t]</div><div> val bold: [< super_node_t] list -> [> nonlink_node_t]</div><div> val see: string -> [> link_node_t]</div><div> val mref: string -> nonlink_node_t list -> [> link_node_t]</div><div>end =</div><div>struct</div><div> type nonlink_node_t = [ `Text of string | `Bold of Node.super_node_t list ]</div><div> type link_node_t = [ `See of string | `Mref of string * nonlink_node_t list ]</div><div> type super_node_t = [ nonlink_node_t | link_node_t ]</div><div><br></div><div> let text txt = `Text txt</div><div> let bold seq = `Bold (seq :> super_node_t list)</div><div> let see ref = `See ref</div><div> let mref ref seq = `Mref (ref, seq)</div><div>end</div><div><br></div><div><br></div><div>The second problem, while not a show-stopper, may open a hole for misuse of</div><div>the module, so I would rather get it fixed. Basically, while the module</div><div>provides constructor functions to build nodes, nothing prevents the user</div><div>from bypassing them and constructing nodes manually. The obvious solution</div><div>of declaring the types "private" results in an "This fixed type has no row</div><div>variable" error. Any way around it?</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>3) Name of currently executing function</div><div>Archive: <<a href="http://groups.google.com/group/fa.caml/browse_thread/thread/25c9706b89196140#">http://groups.google.com/group/fa.caml/browse_thread/thread/25c9706b89196140#</a>></div><div>------------------------------------------------------------------------</div><div>** Dave Benjamin asked and blue storm answered:</div><div><br></div><div>> Is there any way to find out the name of the currently executing </div><div>> function from within an OCaml program? I guess, technically, I'm </div><div>> interested in the grandparent. Something that would allow this: </div><div>> </div><div>> let log msg = </div><div>> Printf.eprintf "%s: %s\n%!" </div><div>> (get_caller_function_name ()) </div><div>> msg </div><div>> </div><div>> I'm guessing the above is not possible, but perhaps there's some way to </div><div>> accomplish this using some combination of camlp4, back traces, </div><div>> profiling, or debugging?</div><div><br></div><div>Here is a little camlp4 code for an ad-hoc solution :</div><div><<a href="http://bluestorm.info/camlp4/Camlp4GenericProfiler.ml">http://bluestorm.info/camlp4/Camlp4GenericProfiler.ml</a>></div><div><br></div><div>It's based upon the Camlp4Filters/Camlp4Profiler.ml from the camlp4</div><div>distribution.</div><div>The GenericMake functor will traverse your code and apply the</div><div>parametrized function to the body of each function declaration. You</div><div>can use it with a functor providing a (with_fun_name : string -></div><div>Ast.expr -> Ast.expr), transforming the Ast to your liking, given the</div><div>function name.</div><div><br></div><div>I've written a small LoggingDecorator module that operates on the</div><div>__LOG__ identifier. Example code :</div><div> let __LOG_FUNC__ func msg = Printf.eprintf "in function %s: %s\n%!" func msg</div><div> let test_function p = if not p then __LOG__ "p is false !"</div><div><br></div><div>It will replace the __LOG__ identifier with a __LOG_FUNC__ "p".</div><div><br></div><div>You can change that behavior, in particular you could be interested</div><div>(for logging purpose) in the location of the function declaration, not</div><div>only his name : see how the initial Camlp4Profiler behavior (wich i</div><div>kept in the ProfilingDecorator) do that (Loc.dump).</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>Using folding to read the cwn in vim 6+</div><div>------------------------------------------------------------------------</div><div>Here is a quick trick to help you read this CWN if you are viewing it using</div><div>vim (version 6 or greater).</div><div><br></div><div>:set foldmethod=expr</div><div>:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'<1':1</div><div>zM</div><div>If you know of a better way, please let me know.</div><div><br></div><div>========================================================================</div><div>Old cwn</div><div>------------------------------------------------------------------------</div><div><br></div><div>If you happen to miss a CWN, you can send me a message</div><div>(<a href="mailto:alan.schmitt@polytechnique.org">alan.schmitt@polytechnique.org</a>) and I'll mail it to you, or go take a look at</div><div>the archive (<<a href="http://alan.petitepomme.net/cwn/">http://alan.petitepomme.net/cwn/</a>>) or the RSS feed of the</div><div>archives (<<a href="http://alan.petitepomme.net/cwn/cwn.rss">http://alan.petitepomme.net/cwn/cwn.rss</a>>). If you also wish</div><div>to receive it every week by mail, you may subscribe online at</div><div><<a href="http://lists.idyll.org/listinfo/caml-news-weekly/">http://lists.idyll.org/listinfo/caml-news-weekly/</a>> .</div><div><br></div><div>========================================================================</div><div class="AppleMailSignature" id="E12A09DE-ADCF-40D6-B7D4-306ED5CADD30"> <div><br class="khtml-block-placeholder"></div><div>-- </div><div>Alan Schmitt <<a href="http://alan.petitepomme.net/">http://alan.petitepomme.net/</a>></div><div><br class="khtml-block-placeholder"></div><div>The hacker: someone who figured things out and made something cool happen.</div><div> .O.</div><div> ..O</div><div> OOO</div><br class="Apple-interchange-newline"> </div><br></body></html>