<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Feb 15, 2008, at 1:33 AM, Vesa Karvonen wrote:</div><blockquote type="cite">&nbsp;fun f x =<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myprint "hello\n" &gt;&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read &gt;&gt;= (fn x =&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read &gt;&gt;= (fn y =&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myprint (x ^ y ^ "\n")))</blockquote><div><br class="webkit-block-placeholder"></div>Well, I was hoping it might somehow be possible to come closer to Haskell's:</div><div><br class="webkit-block-placeholder"></div><div>do myprint "hello"</div><div>&nbsp;&nbsp; &nbsp; x &lt;- read</div><div>&nbsp;&nbsp; &nbsp; y &lt;- read</div><div>&nbsp;&nbsp; &nbsp; myprint (x ^ y ^ "\n")</div><div><br class="webkit-block-placeholder"></div><div>I thought someone might know a more elegant style. When you have 4+ steps and a couple branching cases, the brackets become a problem. -- I am not an emacs user.</div><div><br></div><div><blockquote type="cite"><blockquote type="cite"><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">The problem I'm running up against is that only 'let' clauses and</span></blockquote><blockquote type="cite"> function declarations can introduce variable scope. &nbsp;AFAICT, the let<br></blockquote><blockquote type="cite"> clause prevents me from popping out of the method after installing a<br></blockquote><blockquote type="cite"> signal handler.<br></blockquote><br>Do you have a specific reason to avoid threads? &nbsp;With threads you<br>could avoid using monads and just write the program in direct style.<br>Your example would become:<br><br> &nbsp;fun f x s = let<br> &nbsp;&nbsp;&nbsp;&nbsp;val () = print "hello\n"<br> &nbsp;&nbsp;&nbsp;&nbsp;val x = read s<br> &nbsp;&nbsp;&nbsp;&nbsp;val y = read s<br> &nbsp;in<br> &nbsp;&nbsp;&nbsp;&nbsp;print (x ^ y ^ "\n")<br> &nbsp;end</blockquote><div><br></div><div>Threads are very nice and tempting. However, if you have parallel things to execute, threads are actually restrictive. Using the functional callback style means you can write things like:</div><div><br class="webkit-block-placeholder"></div><div>onceAnyFinishIn [ send "x", send "y", &nbsp;send "z" ] doThis</div><div>onceAllFinishIn ...</div><div><br class="webkit-block-placeholder"></div><div>Also, most of these event chains are relatively short lived. Maybe I'm wrong, but I think threads would be quite wasteful in this case.</div><div><br></div><blockquote type="cite"><blockquote type="cite"><font class="Apple-style-span" color="#144FAE">T</font>he function approach suffers due to the syntax of SML.<br></blockquote><br>Yes, I agree that the required parenthesis are a bit of a nuisance. &nbsp;I<br>would personally consider changing the syntax of SML to allow fn<br>-expressions without parentheses in these contexts like in Haskell.</blockquote><div><br class="webkit-block-placeholder"></div>I assumed there is some reason the ()s are required..? Maybe to avoid the problems nested 'case' statements have?</div><div><br class="webkit-block-placeholder"></div><div><blockquote type="cite">I find the let -syntax fine for functional programming, but somewhat<br>verbose for imperative programming (note the "val () =" in the earlier<br>example). &nbsp;I would personally ditch the let -syntax and change the<br>syntax of SML's sequence expressions to allow bindings like at the top<br>level. &nbsp;This would make imperative programming more convenient. &nbsp;The<br>thread based version would become:<br><br> &nbsp;fun f x s =<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(print "hello\n"<br> &nbsp;&nbsp;&nbsp;&nbsp;; val x = read s<br> &nbsp;&nbsp;&nbsp;&nbsp;; val y = read s<br> &nbsp;&nbsp;&nbsp;&nbsp;; print (x ^ y ^ "\n"))</blockquote><div><br class="webkit-block-placeholder"></div><div>This is one of two things I like about OCaml as compared to SML. The other is that constructors must be capitalized (so no brackets are needed in patterns).</div><div><br></div><blockquote type="cite"><blockquote type="cite">Does someone have a tidy way of writing code like this?</blockquote>If you can't stand the parentheses, I would recommend considering threads.</blockquote><br>I suppose I'll have to live with them then.</div><div><br><blockquote type="cite"><blockquote type="cite">Also, I am concerned by MLton's closure conversion. &nbsp;With this style of<br></blockquote><blockquote type="cite"> programming, there are a *lot* of bound variables which pile up towards<br></blockquote><blockquote type="cite"> the end of the event chain. &nbsp;As I understand it, the closure of MLton<br></blockquote><blockquote type="cite"> is converted into a datatype which represents the function to call +<br></blockquote><blockquote type="cite"> it's free variables. &nbsp;The longer these chains of event handlers get,<br></blockquote><blockquote type="cite"> the more free variables in the later functions. &nbsp;My concern is that it<br></blockquote><blockquote type="cite"> will cost me a lot to convert these datatypes. &nbsp;I am under the<br></blockquote><blockquote type="cite"> impression MLton will flatten them out into one record at each step<br></blockquote><blockquote type="cite"> rather -&gt; O(n^2) cost for n steps of function nesting (if nearly all n<br></blockquote><blockquote type="cite"> variables are used in the last step, which is quite typical). &nbsp;Should I<br></blockquote><blockquote type="cite"> be worried?<br></blockquote><br>I don't know enough about the specifics of MLton's closure conversion,<br>but I would personally be more worried if MLton wouldn't be doing<br>something like that to avoid space leaks.</blockquote></div><br><div>Yes. I share your concern. In the end it probably won't matter if MLton copies repeatedly. I just find waste that's out of my control irksome.&nbsp;</div><div><br class="webkit-block-placeholder"></div></body></html>