Re: Rosetta code added in OCaml, please check
"Manfred Lotz [email protected] [ocaml_beginners]" <[email protected]> Tue, 27 Dec 2016 21:36:17 +0100
| Newsgroups | gmane.comp.lang.ocaml.beginners |
|---|---|
| Message-ID | <[email protected]> |
--BeYZuhdP966maW1m5m0IuBnENnm2IWVS8310mgQ Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Tue, 27 Dec 2016 13:30:37 -0500 "Gabriel Scherer [email protected] [ocaml_beginners]" <[email protected]> wrote: > Looking back at the code again, there is one minor detail that you > may be interested in: it is good in OCaml to be suspicious of string > concatenation. (The reason why is performance: (s1 ^ s2) allocates a > new string as long as s1 and s2 combined, and copies them, which is > often unnecessary. If you do this in a loop with a string grower > bigger and bigger it can even result in unplanned quadratic > behaviors, but this is not the case here.) > Thanks for this. > This code is clearly not optimized for efficiency, so a moderate use > of string concatenation is just fine: there is nothing wrong with the > code as-is. On the other hand, it does make sense to wonder how to > express the same thing without: if it is possible at no cost to > readability, it is an interesting option. > > In the ordinal example, I think that there is a nice option without > concatenation, which is to have a call in the loop of the following > form: > > Printf.printf "%d%s " n (ordinal_suffix n); > I removed then concatenation in the suffix creation, and used your Printf.printf suggestion which is nice and clean. > (A cascade of (print_int; print_string; print_char ' ') would be > *slightly* more efficient but I think also less pleasant to read.) > I'm not sure about this. I did a test to create 2*10^7 ordinals, writing them to /dev/null. Printf.printf was significant faster than the (print_int; print_string; print_char ' ') combination. > This works well here because we print. You may encounter other > contexts where you want to return a string. Then: > - one possible alternative to repeated string concatenations is to > accumulate all the sub-strings in a list, and call (String.concat : (* > separator *) string -> string list -> string) only once at the end. > This is efficient. > - another is the use of Buffer module for (efficient) string > accumulation into an extensible buffer. (Printf.bprintf buf) allows > to use printf-style commands to add elements to a buffer. > http://caml.inria.fr/pub/docs/manual-ocaml/libref/Buffer.html > Great. I'll look into this. Thanks again for your very good advice. Best, Manfred > On Tue, Dec 27, 2016 at 1:19 PM, Manfred Lotz [email protected] > [ocaml_beginners] <[email protected]> wrote: > > > Hi Gabriel, > > First, thanks a lot for looking into this. > > > > On Tue, 27 Dec 2016 11:00:23 -0500 > > "Gabriel Scherer [email protected] [ocaml_beginners]" > > <[email protected]> wrote: > > > > > Hi Manfred, > > > > > > Thanks for the interesting question. Having your code reviewed is > > > an excellent way to make progress. > > > > > > For history variables, your code is fine, but you should consider > > > using the Stack module instead of re-implementing yourself using > > > mutable lists. > > > > You are right. I changed the implementation using the Stack module. > > > > > > > (Independently, when you have a record with a single > > > mutable field, you could consider using the standard "ref" type > > > instead; but sometimes having your own record type actually helps > > > readability.) > > > > > > > I chose a record because if something gets added (time stamp or so) > > then it is just about adding a field. > > > > > > > For the enumeration of ordinal numbers, there are two things that > > > I am not fond of in your code: > > > > > > 1. I think that "when" is a dangerous construction to use and its > > > use should be de-emphasized, because it encourages code that > > > relies on ordering in non-trivial way, diminishing a lot of the > > > value of pattern-matching. The fact that, apart from the "when" > > > clause, you are not using expressive patterns in any way is the > > > sign of a code smell in my book. When I teach beginners, I ask > > > them to only pattern-match on algebraic datatypes. I would > > > encourage you to rewrite this part with an explicit "if ... else > > > if ..." cascade. > > > > This is a very interesting comment. I wasn't aware of this. Thinking > > about it (I will look into this more closely) it makes sense. So, I > > chose your suggestion of a cascaded "if...else if...". > > > > > You could also decide to factorize the three cases with a function > > > > > > let non_th n = > > > let d = n mod 10 in > > > d >= 1 && d <= 3 && n mod 100 <> (10 + d) in > > > > > > 2. The creation of the array in "f" seems unnecessary to me. > > > Using a "for" loop would result in simpler code, whose structure > > > would be more directly apparent to readers. > > > > > > > You are right, of course. I changed it accordingly. I also changed > > the name of 'f' to 'show_numbers' which is surely a better name than > > just 'f'. > > > > > (If you like functional pipelines with higher-order iterator, you > > > may be pleased by the following reformulation of your code, that > > > I think is still not as good as a for loop: > > > > > > Array.init ... > > > |> Array.iter ... > > > |> print_newline > > > ) > > > > > > > I like it very much in some situations. But your suggestion of using > > for loop is preferable without question. > > > > > In languages with powerful features, I think it is good to keep a > > > principle of local simplicity: use the simplest feature that lets > > > you express the problem without undue redundancy. (This rule of > > > thumb is in tension with the other rules that the parts of a > > > given block of code should be at roughly the same abstraction > > > level: if you need to do X, Y, Z in sequence, and only Y can be > > > expressed simply with a for-loop, it's better to keep a > > > homogeneous style.) > > > > > > Cheers > > > > > > > Thanks again for looking so closely into my code. If I happen to > > meet you face-to-face I owe you a wine, beer or whatever you like > > best. :-) > > > > > > -- > > Best, Manfred > > > > > On Tue, Dec 27, 2016 at 10:40 AM, Manfred Lotz > > > [email protected] [ocaml_beginners] > > > <[email protected]> wrote: > > > > Hi there, > > > > I have added OCaml solutions for two simple tasks at > > > > Rosettacode. > > > > > > > > As a mere beginner in OCaml I don't want to add bad quality > > > > stuff at Rosettacode, and thus (worst case) in the end make > > > > people believe OCaml were a bad language. > > > > > > > > Therefore, I would be happy if some of the more knowledgeable > > > > people around here could check if the code I added is OK. > > > > > > > > http://rosettacode.org/wiki/History_variables#OCaml > > > > http://rosettacode.org/wiki/N%27th#OCaml > > > > > > > > > > > > Thanks a lot. > > > > > > > > Manfred > > > > > > > > > > > > ------------------------------------ > > > > Posted by: Manfred Lotz <[email protected]> > > > > ------------------------------------ > > > > > > > > Archives up to December 31, 2011 are also downloadable at > > > > http://www.connettivo.net/cntprojects/ocaml_beginners > > > > The archives of the very official ocaml list (the seniors' one) > > > > can be found at http://caml.inria.fr > > > > Attachments are banned and you're asked to be polite, avoid > > > > flames etc. ------------------------------------ > > > > > > > > Yahoo Groups Links > > > > > > > > > > > > > > > > > > > > > > > > ------------------------------------ > > Posted by: Manfred Lotz <[email protected]> > > ------------------------------------ > > > > Archives up to December 31, 2011 are also downloadable at > > http://www.connettivo.net/cntprojects/ocaml_beginners > > The archives of the very official ocaml list (the seniors' one) can > > be found at http://caml.inria.fr > > Attachments are banned and you're asked to be polite, avoid flames > > etc. ------------------------------------ > > > > Yahoo Groups Links > > > > > > > > --BeYZuhdP966maW1m5m0IuBnENnm2IWVS8310mgQ Content-Type: text/html; charset=US-ASCII Content-Transfer-Encoding: 7bit <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> </head> <body style="background-color: #fff;"> <span style="display:none"> </span> <!--~-|**|PrettyHtmlStartT|**|-~--> <div id="ygrp-mlmsg" style="position:relative;"> <div id="ygrp-msg" style="z-index: 1;"> <!--~-|**|PrettyHtmlEndT|**|-~--> <div id="ygrp-text" > <p>On Tue, 27 Dec 2016 13:30:37 -0500<br> "Gabriel Scherer [email protected] [ocaml_beginners]"<br> <[email protected]> wrote:<br> <br> > Looking back at the code again, there is one minor detail that you<br> > may be interested in: it is good in OCaml to be suspicious of string<br> > concatenation. (The reason why is performance: (s1 ^ s2) allocates a<br> > new string as long as s1 and s2 combined, and copies them, which is<br> > often unnecessary. If you do this in a loop with a string grower<br> > bigger and bigger it can even result in unplanned quadratic<br> > behaviors, but this is not the case here.)<br> > <br> <br> Thanks for this. <br> <br> > This code is clearly not optimized for efficiency, so a moderate use<br> > of string concatenation is just fine: there is nothing wrong with the<br> > code as-is. On the other hand, it does make sense to wonder how to<br> > express the same thing without: if it is possible at no cost to<br> > readability, it is an interesting option.<br> > <br> > In the ordinal example, I think that there is a nice option without<br> > concatenation, which is to have a call in the loop of the following<br> > form:<br> > <br> > Printf.printf "%d%s " n (ordinal_suffix n);<br> > <br> <br> I removed then concatenation in the suffix creation, and used<br> your Printf.printf suggestion which is nice and clean.<br> <br> > (A cascade of (print_int; print_string; print_char ' ') would be<br> > *slightly* more efficient but I think also less pleasant to read.)<br> > <br> <br> I'm not sure about this. I did a test to create 2*10^7 ordinals,<br> writing them to /dev/null. Printf.printf was significant faster than<br> the (print_int; print_string; print_char ' ') combination.<br> <br> > This works well here because we print. You may encounter other<br> > contexts where you want to return a string. Then:<br> > - one possible alternative to repeated string concatenations is to<br> > accumulate all the sub-strings in a list, and call (String.concat : (*<br> > separator *) string -> string list -> string) only once at the end.<br> > This is efficient.<br> > - another is the use of Buffer module for (efficient) string<br> > accumulation into an extensible buffer. (Printf.bprintf buf) allows<br> > to use printf-style commands to add elements to a buffer.<br> > http://caml.inria.fr/pub/docs/manual-ocaml/libref/Buffer.html<br> > <br> <br> Great. I'll look into this.<br> <br> Thanks again for your very good advice. <br> <br> Best, Manfred<br> <br> > On Tue, Dec 27, 2016 at 1:19 PM, Manfred Lotz [email protected]<br> > [ocaml_beginners] <[email protected]> wrote:<br> > <br> > > Hi Gabriel,<br> > > First, thanks a lot for looking into this.<br> > ><br> > > On Tue, 27 Dec 2016 11:00:23 -0500<br> > > "Gabriel Scherer [email protected] [ocaml_beginners]"<br> > > <[email protected]> wrote:<br> > > <br> > > > Hi Manfred,<br> > > ><br> > > > Thanks for the interesting question. Having your code reviewed is<br> > > > an excellent way to make progress.<br> > > ><br> > > > For history variables, your code is fine, but you should consider<br> > > > using the Stack module instead of re-implementing yourself using<br> > > > mutable lists. <br> > ><br> > > You are right. I changed the implementation using the Stack module.<br> > ><br> > > <br> > > > (Independently, when you have a record with a single<br> > > > mutable field, you could consider using the standard "ref" type<br> > > > instead; but sometimes having your own record type actually helps<br> > > > readability.)<br> > > > <br> > ><br> > > I chose a record because if something gets added (time stamp or so)<br> > > then it is just about adding a field.<br> > ><br> > > <br> > > > For the enumeration of ordinal numbers, there are two things that<br> > > > I am not fond of in your code:<br> > > ><br> > > > 1. I think that "when" is a dangerous construction to use and its<br> > > > use should be de-emphasized, because it encourages code that<br> > > > relies on ordering in non-trivial way, diminishing a lot of the<br> > > > value of pattern-matching. The fact that, apart from the "when"<br> > > > clause, you are not using expressive patterns in any way is the<br> > > > sign of a code smell in my book. When I teach beginners, I ask<br> > > > them to only pattern-match on algebraic datatypes. I would<br> > > > encourage you to rewrite this part with an explicit "if ... else<br> > > > if ..." cascade. <br> > ><br> > > This is a very interesting comment. I wasn't aware of this. Thinking<br> > > about it (I will look into this more closely) it makes sense. So, I<br> > > chose your suggestion of a cascaded "if...else if...".<br> > > <br> > > > You could also decide to factorize the three cases with a function<br> > > ><br> > > > let non_th n =<br> > > > let d = n mod 10 in<br> > > > d >= 1 && d <= 3 && n mod 100 <> (10 + d) in<br> > > ><br> > > > 2. The creation of the array in "f" seems unnecessary to me.<br> > > > Using a "for" loop would result in simpler code, whose structure<br> > > > would be more directly apparent to readers.<br> > > > <br> > ><br> > > You are right, of course. I changed it accordingly. I also changed<br> > > the name of 'f' to 'show_numbers' which is surely a better name than<br> > > just 'f'.<br> > > <br> > > > (If you like functional pipelines with higher-order iterator, you<br> > > > may be pleased by the following reformulation of your code, that<br> > > > I think is still not as good as a for loop:<br> > > ><br> > > > Array.init ... <br> > > > |> Array.iter ...<br> > > > |> print_newline <br> > > > )<br> > > > <br> > ><br> > > I like it very much in some situations. But your suggestion of using<br> > > for loop is preferable without question.<br> > > <br> > > > In languages with powerful features, I think it is good to keep a<br> > > > principle of local simplicity: use the simplest feature that lets<br> > > > you express the problem without undue redundancy. (This rule of<br> > > > thumb is in tension with the other rules that the parts of a<br> > > > given block of code should be at roughly the same abstraction<br> > > > level: if you need to do X, Y, Z in sequence, and only Y can be<br> > > > expressed simply with a for-loop, it's better to keep a<br> > > > homogeneous style.)<br> > > ><br> > > > Cheers<br> > > > <br> > ><br> > > Thanks again for looking so closely into my code. If I happen to<br> > > meet you face-to-face I owe you a wine, beer or whatever you like<br> > > best. :-)<br> > ><br> > ><br> > > --<br> > > Best, Manfred<br> > > <br> > > > On Tue, Dec 27, 2016 at 10:40 AM, Manfred Lotz<br> > > > [email protected] [ocaml_beginners]<br> > > > <[email protected]> wrote: <br> > > > > Hi there,<br> > > > > I have added OCaml solutions for two simple tasks at<br> > > > > Rosettacode.<br> > > > ><br> > > > > As a mere beginner in OCaml I don't want to add bad quality<br> > > > > stuff at Rosettacode, and thus (worst case) in the end make<br> > > > > people believe OCaml were a bad language.<br> > > > ><br> > > > > Therefore, I would be happy if some of the more knowledgeable<br> > > > > people around here could check if the code I added is OK.<br> > > > ><br> > > > > http://rosettacode.org/wiki/History_variables#OCaml<br> > > > > http://rosettacode.org/wiki/N%27th#OCaml<br> > > > ><br> > > > ><br> > > > > Thanks a lot.<br> > > > ><br> > > > > Manfred<br> > > > ><br> > > > ><br> > > > > ------------------------------------<br> > > > > Posted by: Manfred Lotz <[email protected]><br> > > > > ------------------------------------<br> > > > ><br> > > > > Archives up to December 31, 2011 are also downloadable at<br> > > > > http://www.connettivo.net/cntprojects/ocaml_beginners<br> > > > > The archives of the very official ocaml list (the seniors' one)<br> > > > > can be found at http://caml.inria.fr<br> > > > > Attachments are banned and you're asked to be polite, avoid<br> > > > > flames etc. ------------------------------------<br> > > > ><br> > > > > Yahoo Groups Links<br> > > > ><br> > > > ><br> > > > ><br> > > > > <br> > ><br> > ><br> > ><br> > > ------------------------------------<br> > > Posted by: Manfred Lotz <[email protected]><br> > > ------------------------------------<br> > ><br> > > Archives up to December 31, 2011 are also downloadable at<br> > > http://www.connettivo.net/cntprojects/ocaml_beginners<br> > > The archives of the very official ocaml list (the seniors' one) can<br> > > be found at http://caml.inria.fr<br> > > Attachments are banned and you're asked to be polite, avoid flames<br> > > etc. ------------------------------------<br> > ><br> > > Yahoo Groups Links<br> > ><br> > ><br> > ><br> > > <br> <br> </p> </div> <!--~-|**|PrettyHtmlStart|**|-~--> <div style="color: #fff; height: 0;">__._,_.___</div> <div style="clear:both"> </div> <div id="fromDMARC" style="margin-top: 10px;"> <hr style="height:2px ; border-width:0; color:#E3E3E3; background-color:#E3E3E3;"> Posted by: Manfred Lotz <[email protected]> <hr style="height:2px ; border-width:0; color:#E3E3E3; background-color:#E3E3E3;"> </div> <div style="clear:both"> </div> <table cellspacing=4px style="margin-top: 10px; margin-bottom: 10px; color: #2D50FD;"> <tbody> <tr> <td style="font-size: 12px; font-family: arial; font-weight: bold; padding: 7px 5px 5px;" > <a style="text-decoration: none; color: #2D50FD" href="https://groups.yahoo.com/neo/groups/ocaml_beginners/conversations/messages/14729;_ylc=X3oDMTJxczNnYWt1BF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BG1zZ0lkAzE0NzI5BHNlYwNmdHIEc2xrA3JwbHkEc3RpbWUDMTQ4Mjg3MDk4MA--?act=reply&messageNum=14729">Reply via web post</a> </td> <td>•</td> <td style="font-size: 12px; font-family: arial; padding: 7px 5px 5px;" > <a href="mailto:[email protected]?subject=Re%3A%20%22ocaml_beginners%22%3A%3A%5B%5D%20Rosetta%20code%20added%20in%20OCaml%2C%20please%20check" style="text-decoration: none; color: #2D50FD;"> Reply to sender </a> </td> <td>•</td> <td style="font-size: 12px; font-family: arial; padding: 7px 5px 5px;"> <a href="mailto:[email protected]?subject=Re%3A%20%22ocaml_beginners%22%3A%3A%5B%5D%20Rosetta%20code%20added%20in%20OCaml%2C%20please%20check" style="text-decoration: none; color: #2D50FD"> Reply to group </a> </td> <td>•</td> <td style="font-size: 12px; font-family: arial; padding: 7px 5px 5px;" > <a href="https://groups.yahoo.com/neo/groups/ocaml_beginners/conversations/newtopic;_ylc=X3oDMTJlbGswdjV1BF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwNmdHIEc2xrA250cGMEc3RpbWUDMTQ4Mjg3MDk4MA--" style="text-decoration: none; color: #2D50FD">Start a New Topic</a> </td> <td>•</td> <td style="font-size: 12px; font-family: arial; padding: 7px 5px 5px;color: #2D50FD;" > <a href="https://groups.yahoo.com/neo/groups/ocaml_beginners/conversations/topics/14725;_ylc=X3oDMTM2M2tyODdpBF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BG1zZ0lkAzE0NzI5BHNlYwNmdHIEc2xrA3Z0cGMEc3RpbWUDMTQ4Mjg3MDk4MAR0cGNJZAMxNDcyNQ--" style="text-decoration: none; color: #2D50FD;">Messages in this topic</a> (5) </td> </tr> </tbody> </table> <div id="megaphoneModule"> <hr style="height:2px ; border-width:0; color:#E3E3E3; background-color:#E3E3E3;"> <div> <div class="stream" style="margin-bottom:10px;"> <div style="background-color:white;"> <div class="sn-img" style="display:inline;"><img name="tn_file" style="padding:0px 10px;vertical-align:top;margin-top:5px;" src="https://s.yimg.com/ru/static/images/yg/img/megaphone/1464031581_phpFA8bON" height="82" width="82"></div> <div class="mod-txt" style="display:inline-block;"> <a rel="nofollow" name="sub_url" target="_blank" href="https://yho.com/1wwmgg" style="color:#0000FF;display:block;margin-left:5px;text-decoration:none;"><span style="font-size:15px;">Have you tried the highest rated email app?</span></a> <div style="max-width:530px;padding:2px 5px;">With 4.5 stars in iTunes, the Yahoo Mail app is the highest rated email app on the market. What are you waiting for? Now you can access all your inboxes (Gmail, Outlook, AOL and more) in one place. Never delete an email again with 1000GB of free cloud storage.</div> </div> </div> </div> </div> <hr style="height:2px ; border-width:0; color:#E3E3E3; background-color:#E3E3E3;"> </div> <!------- Start Nav Bar ------> <div id="ygrp-grfd" style="font-family: Verdana; font-size: 12px; padding: 15px 0;"> <!-- |**|begin egp html banner|**| --> Archives up to December 31, 2011 are also downloadable at <a href="http://www.connettivo.net/cntprojects/ocaml_beginners">http://www.connettivo.net/cntprojects/ocaml_beginners</a><BR> The archives of the very official ocaml list (the seniors' one) can be found at <a href="http://caml.inria.fr">http://caml.inria.fr</a><BR> Attachments are banned and you're asked to be polite, avoid flames etc. <!-- |**|end egp html banner|**| --> </div> <!-- |**|begin egp html banner|**| --> <div id="ygrp-vital" style="background-color: #f2f2f2; font-family: Verdana; font-size: 10px; margin-bottom: 10px; padding: 10px;"> <span id="vithd" style="font-weight: bold; color: #333; text-transform: uppercase; "><a href="https://groups.yahoo.com/neo/groups/ocaml_beginners/info;_ylc=X3oDMTJlZXExMnJlBF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwN2dGwEc2xrA3ZnaHAEc3RpbWUDMTQ4Mjg3MDk4MA--" style="text-decoration: none;">Visit Your Group</a></span> <ul style="list-style-type: none; margin: 0; padding: 0; display: inline;"> <li style="border-right: 1px solid #000; font-weight: 700; display: inline; padding: 0 5px; margin-left: 0;"> <span class="cat"><a href="https://groups.yahoo.com/neo/groups/ocaml_beginners/members/all;_ylc=X3oDMTJmZnFyM2liBF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwN2dGwEc2xrA3ZtYnJzBHN0aW1lAzE0ODI4NzA5ODA-" style="text-decoration: none;">New Members</a></span> <span class="ct" style="color: #ff7900;">1</span> </li> </ul> </div> <div id="ft" style="font-family: Arial; font-size: 11px; margin-top: 5px; padding: 0 2px 0 0; clear: both;"> <a href="https://groups.yahoo.com/neo;_ylc=X3oDMTJkY2tlbGdsBF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwNmdHIEc2xrA2dmcARzdGltZQMxNDgyODcwOTgw" style="float: left;"><img src="http://l.yimg.com/ru/static/images/yg/img/email/new_logo/logo-groups-137x15.png" height="15" width="137" alt="Yahoo! Groups" style="border: 0;"/></a> <div style="color: #747575; float: right;"> • <a href="https://info.yahoo.com/privacy/us/yahoo/groups/details.html" style="text-decoration: none;">Privacy</a> • <a href="mailto:[email protected]?subject=Unsubscribe" style="text-decoration: none;">Unsubscribe</a> • <a href="https://info.yahoo.com/legal/us/yahoo/utos/terms/" style="text-decoration: none;">Terms of Use</a> </div> </div> <br> <!-- |**|end egp html banner|**| --> </div> <!-- ygrp-msg --> <!-- Sponsor --> <!-- |**|begin egp html banner|**| --> <div id="ygrp-sponsor" style="width:160px; float:right; clear:none; margin:0 0 25px 0; background: #fff;"> <!-- Start Recommendations --> <div id="ygrp-reco"> </div> <!-- End Recommendations --> </div> <!-- |**|end egp html banner|**| --> <div style="clear:both; color: #FFF; font-size:1px;">.</div> </div> <img src="http://geo.yahoo.com/serv?s=97359714/grpId=4999194/grpspId=1705006764/msgId=14729/stime=1482870980" width="1" height="1"> <br> <img src="http://y.analytics.yahoo.com/fpc.pl?ywarid=515FB27823A7407E&a=10001310322279&js=no&resp=img&cf12=CP" width="1" height="1"> <div style="color: #fff; height: 0;">__,_._,___</div> <!--~-|**|PrettyHtmlEnd|**|-~--> </body> <!--~-|**|PrettyHtmlStart|**|-~--> <head> <style type="text/css"> <!-- #ygrp-mkp { border: 1px solid #d8d8d8; font-family: Arial; margin: 10px 0; padding: 0 10px; } #ygrp-mkp hr { border: 1px solid #d8d8d8; } #ygrp-mkp #hd { color: #628c2a; font-size: 85%; font-weight: 700; line-height: 122%; margin: 10px 0; } #ygrp-mkp #ads { margin-bottom: 10px; } #ygrp-mkp .ad { padding: 0 0; } #ygrp-mkp .ad p { margin: 0; } #ygrp-mkp .ad a { color: #0000ff; text-decoration: none; } #ygrp-sponsor #ygrp-lc { font-family: Arial; } #ygrp-sponsor #ygrp-lc #hd { margin: 10px 0px; font-weight: 700; font-size: 78%; line-height: 122%; } #ygrp-sponsor #ygrp-lc .ad { margin-bottom: 10px; padding: 0 0; } #actions { font-family: Verdana; font-size: 11px; padding: 10px 0; } #activity { background-color: #e0ecee; float: left; font-family: Verdana; font-size: 10px; padding: 10px; } #activity span { font-weight: 700; } #activity span:first-child { text-transform: uppercase; } #activity span a { color: #5085b6; text-decoration: none; } #activity span span { color: #ff7900; } #activity span .underline { text-decoration: underline; } .attach { clear: both; display: table; font-family: Arial; font-size: 12px; padding: 10px 0; width: 400px; } .attach div a { text-decoration: none; } .attach img { border: none; padding-right: 5px; } .attach label { display: block; margin-bottom: 5px; } .attach label a { text-decoration: none; } blockquote { margin: 0 0 0 4px; } .bold { font-family: Arial; font-size: 13px; font-weight: 700; } .bold a { text-decoration: none; } dd.last p a { font-family: Verdana; font-weight: 700; } dd.last p span { margin-right: 10px; font-family: Verdana; font-weight: 700; } dd.last p span.yshortcuts { margin-right: 0; } div.attach-table div div a { text-decoration: none; } div.attach-table { width: 400px; } div.file-title a, div.file-title a:active, div.file-title a:hover, div.file-title a:visited { text-decoration: none; } div.photo-title a, div.photo-title a:active, div.photo-title a:hover, div.photo-title a:visited { text-decoration: none; } div#ygrp-mlmsg #ygrp-msg p a span.yshortcuts { font-family: Verdana; font-size: 10px; font-weight: normal; } .green { color: #628c2a; } .MsoNormal { margin: 0 0 0 0; } o { font-size: 0; } #photos div { float: left; width: 72px; } #photos div div { border: 1px solid #666666; height: 62px; overflow: hidden; width: 62px; } #photos div label { color: #666666; font-size: 10px; overflow: hidden; text-align: center; white-space: nowrap; width: 64px; } #reco-category { font-size: 77%; } #reco-desc { font-size: 77%; } .replbq { margin: 4px; } #ygrp-actbar div a:first-child { /* border-right: 0px solid #000;*/ margin-right: 2px; padding-right: 5px; } #ygrp-mlmsg { font-size: 13px; font-family: Arial, helvetica,clean, sans-serif; *font-size: small; *font: x-small; } #ygrp-mlmsg table { font-size: inherit; font: 100%; } #ygrp-mlmsg select, input, textarea { font: 99% Arial, Helvetica, clean, sans-serif; } #ygrp-mlmsg pre, code { font:115% monospace; *font-size:100%; } #ygrp-mlmsg * { line-height: 1.22em; } #ygrp-mlmsg #logo { padding-bottom: 10px; } #ygrp-msg p a { font-family: Verdana; } #ygrp-msg p#attach-count span { color: #1E66AE; font-weight: 700; } #ygrp-reco #reco-head { color: #ff7900; font-weight: 700; } #ygrp-reco { margin-bottom: 20px; padding: 0px; } #ygrp-sponsor #ov li a { font-size: 130%; text-decoration: none; } #ygrp-sponsor #ov li { font-size: 77%; list-style-type: square; padding: 6px 0; } #ygrp-sponsor #ov ul { margin: 0; padding: 0 0 0 8px; } #ygrp-text { font-family: Georgia; } #ygrp-text p { margin: 0 0 1em 0; } #ygrp-text tt { font-size: 120%; } #ygrp-vital ul li:last-child { border-right: none !important; } --> </style> </head> <!--~-|**|PrettyHtmlEnd|**|-~--> </html> <!-- end group email --> --BeYZuhdP966maW1m5m0IuBnENnm2IWVS8310mgQ--