Re: Bytes module versus String module.

"Gabriel Scherer [email protected] [ocaml_beginners]" <[email protected]> Wed, 8 Feb 2017 00:42:34 +0100
Newsgroups gmane.comp.lang.ocaml.beginners
Message-ID <CAPFanBFvtCfV4zrRBLeT-E+UFpbxiHYx+m7dUuqZo-PSus=Rww@mail.gmail.com>
--001a114561aec8b6390547f94f3f
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

String represents (immutable) text, while Bytes represent (mutable) arrays
of bytes. Right now, we are in a transition period where the string type
played both roles, and in particular was always mutable (which is not a
very good idea): by default, during this transition period, the two types
`string` and `bytes` are compatible (you can use functions of one on the
other). If you enable the `-safe-string` flag, then the two types will be
considered incompatible; using it in your code is good practice, and it
will become the default in a future OCaml version.

Regarding your code:
- repeatedly calling String.sub is inefficient; you want to count the
number of spaces at the beginning and call String.sub just once
- there is no need to use String.make here, you can match on a character
directly ('c' instead of "c")

Your code is relatively typical of people that enjoy recursively processing
lists, and try to apply the same approach to strings. Because the "tail"
operation on strings takes linear (O(n)) instead of constant (O(1)) time,
this is not a very good idea performance-wise. Reading characters at any
position is fine, but the rest (String.sub, string concatenation (^)...)
should be used as sparsely as possible -- preferably not at each recursive
call.

On Tue, Feb 7, 2017 at 11:35 PM, Douglas Lewit [email protected]
[ocaml_beginners] <[email protected]> wrote:

>
>
> Hi everyone,
>
> I wrote the following functions.
>
>
> *(* The function removeSpacesFromString' relies on the function
> removeSpacesFromString.  removeSpacesFromString' takes a string *
> *   such as "How are you doing" and parses it into a list of separate
> words.  In this case for example, removeSpacesFromString' *
> *   will return ["How"; "are"; "you"; "doing"]. *)*
>
>
> *let rec removeSpacesFromString s w l =3D match Bytes.length s with *
> *                                              |0 -> List.rev begin [w] :=
:
> l end*
> *                                              |_ -> match Bytes.make 1 (
> Bytes.get s 0 ) with *
> *                                                    |" " ->
> removeSpacesFromString ( Bytes.sub s 1 ( Bytes.length s - 1 ) )  ""  **([=
w]
> :: l)*
> *                                                    |_   ->
> removeSpacesFromString ( Bytes.sub s 1 ( Bytes.length s - 1 ) ) *
> *                                                               begin w ^
> ( Bytes.make 1 ( Bytes.get s 0 ) )  end l ;;*
>
>
> *let removeSpacesFromString' s =3D List.flatten begin removeSpacesFromStr=
ing
> s "" [] end ;;*
>
>
> The functions work exactly as I want them to, which is great!  But just
> for the sake of experimentation I tried to substitute the "String" module
> for the "Bytes" module into the first function above.  Well guess what?
> Nothing really changed!  I still get the exact same results as before,
> which leads to an interesting question.  How is the Bytes module differen=
t
> from the String module?  I sort of get the impression from the online
> documentation that the Bytes module is the "new and improved" version of
> the String module, but if that's the case then why doesn't INRIA just
> delete the String module from OCaml's Standard Library?  Are the two
> libraries pretty much the same?  How is the Bytes library better than the
> String library?  What would happen if INRIA just decided to remove the
> String library from the next major version of OCaml?
>
> One quick question here before I send my email.  How much does OCaml
> depend on C?  I know that Python and Ruby are essentially very large "C
> applications" in the sense that the interpreters for those languages are
> coded in the C language.  ( Or at least that's what I have read online. )
>  What about OCaml.  How is OCaml's compiler implemented?  Is the OCaml
> compiler written in C?  Or written in something else?
>
> I appreciate your feedback and thanks!
>
> Best,
>
> Douglas Lewit
>
>
>
>=20
>

--001a114561aec8b6390547f94f3f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/htm=
l4/strict.dtd">
<html>
<head>
</head>






=20
<body style=3D"background-color: #fff;">
<span style=3D"display:none">&nbsp;</span>

<!--~-|**|PrettyHtmlStartT|**|-~-->
<div id=3D"ygrp-mlmsg" style=3D"position:relative;">
  <div id=3D"ygrp-msg" style=3D"z-index: 1;">
<!--~-|**|PrettyHtmlEndT|**|-~-->

    <div id=3D"ygrp-text" >
=20=20=20=20=20=20
=20=20=20=20=20=20
      <p><div dir=3D"ltr"><div><div><div><div>String represents (immutable)=
 text, while Bytes represent (mutable) arrays of bytes. Right now, we are i=
n a transition period where the string type played both roles, and in parti=
cular  was always mutable (which is not a very good idea): by default, duri=
ng this transition period, the two types `string` and `bytes` are compatibl=
e (you can use functions of one on the other). If you enable the `-safe-str=
ing` flag, then the two types will be considered incompatible; using it in =
your code is good practice, and it will become the default in a future OCam=
l version.<br><br></div>Regarding your code:<br></div>- repeatedly calling =
String.sub is inefficient; you want to count the number of spaces at the be=
ginning and call String.sub just once<br></div>- there is no need to use St=
ring.make here, you can match on a character directly (&#39;c&#39; instead =
of &quot;c&quot;)<br><br></div>Your code is relatively typical of people th=
at enjoy recursively processing lists, and try to apply the same approach t=
o strings. Because the &quot;tail&quot; operation on strings takes linear (=
O(n)) instead of constant (O(1)) time, this is not a very good idea perform=
ance-wise. Reading characters at any position is fine, but the rest (String=
.sub, string concatenation (^)...) should be used as sparsely as possible -=
- preferably not at each recursive call.<br></div><div class=3D"gmail_extra=
"><br><div class=3D"gmail_quote">On Tue, Feb 7, 2017 at 11:35 PM, Douglas L=
ewit <a href=3D"mailto:[email protected]">[email protected]</a> [ocaml_begi=
nners] <span dir=3D"ltr">&lt;<a href=3D"mailto:ocaml_beginners@yahoogroups.=
com" target=3D"_blank">[email protected]</a>&gt;</span> wrote=
:<br><blockquote class=3D"gmail_quote" style=3D"border-left:1px #ccc solid;=
">






=20=20=20=20=20=20=20=20




<div>





<br><br>




<div dir=3D"ltr"><font size=3D"4">Hi everyone,</font><div><font size=3D"4">=
<br></font></div><div><font size=3D"4">I wrote the following functions.</fo=
nt></div><div><font size=3D"4"><br></font></div><div><font size=3D"4" color=
=3D"#cc0000"><b><br></b></font></div><div><font size=3D"4"><div><b><font co=
lor=3D"#20124d">(* The function removeSpacesFromString&#39; relies on the f=
unction removeSpacesFromString. =C2=A0removeSpacesFromString&#39; takes a s=
tring=C2=A0</font></b></div><div><b><font color=3D"#20124d">=C2=A0 =C2=A0su=
ch as &quot;How are you doing&quot; and parses it into a list of separate w=
ords.=C2=A0 In this case for example, removeSpacesFromString&#39;=C2=A0</fo=
nt></b></div><div><b><font color=3D"#20124d">=C2=A0 =C2=A0will return [&quo=
t;How&quot;; &quot;are&quot;; &quot;you&quot;; &quot;doing&quot;]. *)</font=
></b></div><div><b><font color=3D"#20124d"><br></font></b></div><div><b><fo=
nt color=3D"#20124d"><br></font></b></div><div><b><font color=3D"#20124d">l=
et rec removeSpacesFromString s w l =3D match Bytes.length s with=C2=A0</fo=
nt></b></div><div><b><font color=3D"#20124d">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 |0 -&gt; List.r=
ev begin [w] :: l end</font></b></div><div><b><font color=3D"#20124d">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 |_ -&gt; match Bytes.make 1 ( Bytes.get s 0 ) with=C2=A0</font><=
/b></div><div><b><font color=3D"#20124d">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 |=
&quot; &quot; -&gt; removeSpacesFromString ( Bytes.sub s 1 ( Bytes.length s=
 - 1 ) ) =C2=A0&quot;&quot; =C2=A0</font></b><b><font color=3D"#20124d">([w=
] :: l)</font></b></div><div><b><font color=3D"#20124d">=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 |_ =C2=A0 -&gt; removeSpacesFromString ( Bytes.sub s 1 ( =
Bytes.length s - 1 ) )=C2=A0</font></b></div><div><b><font color=3D"#20124d=
">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0begin w ^ ( Bytes.make 1 ( Bytes.get s 0 ) ) =C2=A0end l ;;</font></b></=
div><div><b><font color=3D"#20124d"><br></font></b></div><div><b><font colo=
r=3D"#20124d"><br></font></b></div><div><b><font color=3D"#20124d">let remo=
veSpacesFromString&#39; s =3D List.flatten begin removeSpacesFromString s &=
quot;&quot; [] end ;;</font></b></div><div><b><font color=3D"#cc0000"><br><=
/font></b></div><div><br></div><div>The functions work exactly as I want th=
em to, which is great!=C2=A0 But just for the sake of experimentation I tri=
ed to substitute the &quot;String&quot; module for the &quot;Bytes&quot; mo=
dule into the first function above.=C2=A0 Well guess what?=C2=A0 Nothing re=
ally changed!=C2=A0 I still get the exact same results as before, which lea=
ds to an interesting question.=C2=A0 How is the Bytes module different from=
 the String module?=C2=A0 I sort of get the impression from the online docu=
mentation that the Bytes module is the &quot;new and improved&quot; version=
 of the String module, but if that&#39;s the case then why doesn&#39;t INRI=
A just delete the String module from OCaml&#39;s Standard Library?=C2=A0 Ar=
e the two libraries pretty much the same?=C2=A0 How is the Bytes library be=
tter than the String library?=C2=A0 What would happen if INRIA just decided=
 to remove the String library from the next major version of OCaml?</div><d=
iv><br></div><div>One quick question here before I send my email.=C2=A0 How=
 much does OCaml depend on C?=C2=A0 I know that Python and Ruby are essenti=
ally very large &quot;C applications&quot; in the sense that the interprete=
rs for those languages are coded in the C language. =C2=A0( Or at least tha=
t&#39;s what I have read online. ) =C2=A0What about OCaml.=C2=A0 How is OCa=
ml&#39;s compiler implemented?=C2=A0 Is the OCaml compiler written in C?=C2=
=A0 Or written in something else?</div><div><br></div><div>I appreciate you=
r feedback and thanks!</div><div><br></div><div>Best,</div><div><br></div><=
div>Douglas Lewit</div><div><br></div></font></div></div>






<br>


<br>




<div width=3D"1" style=3D"color:white;"></div>



</div></blockquote></div><br></div>
</p>

    </div>
=20=20=20=20=20

    <!--~-|**|PrettyHtmlStart|**|-~-->
    <div style=3D"color: #fff; height: 0;">__._,_.___</div>

=20=20=20=20=20=20=20=20=20=20
=20=20
=20

=20=20=20=20
    <div style=3D"clear:both"> </div>

    <div id=3D"fromDMARC" style=3D"margin-top: 10px;">
        <hr style=3D"height:2px ; border-width:0; color:#E3E3E3; background=
-color:#E3E3E3;">
        Posted by: Gabriel Scherer &lt;[email protected]&gt;       =
 <hr style=3D"height:2px ; border-width:0; color:#E3E3E3; background-color:=
#E3E3E3;">
     </div>
    <div style=3D"clear:both"> </div>

    <table cellspacing=3D4px style=3D"margin-top: 10px; margin-bottom: 10px=
; color: #2D50FD;">
      <tbody>
        <tr>
          <td style=3D"font-size: 12px; font-family: arial; font-weight: bo=
ld; padding: 7px 5px 5px;"  >
                          <a style=3D"text-decoration: none; color: #2D50FD=
" href=3D"https://groups.yahoo.com/neo/groups/ocaml_beginners/conversations=
/messages/14759;_ylc=3DX3oDMTJxMm1qMW8wBF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQE=
Z3Jwc3BJZAMxNzA1MDA2NzY0BG1zZ0lkAzE0NzU5BHNlYwNmdHIEc2xrA3JwbHkEc3RpbWUDMTQ=
4NjUxMDk5NQ--?act=3Dreply&messageNum=3D14759">Reply via web post</a>
                      </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;" >
            <a href=3D"mailto:[email protected]?subject=3DRe%3A%20%=
22ocaml_beginners%22%3A%3A%5B%5D%20Bytes%20module%20versus%20String%20modul=
e%2E" style=3D"text-decoration: none; color: #2D50FD;">
               Reply to sender            </a>
          </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;">
            <a href=3D"mailto:[email protected]?subject=3DRe%=
3A%20%22ocaml_beginners%22%3A%3A%5B%5D%20Bytes%20module%20versus%20String%2=
0module%2E" style=3D"text-decoration: none; color: #2D50FD">
              Reply to group            </a>
          </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;" >
            <a href=3D"https://groups.yahoo.com/neo/groups/ocaml_beginners/=
conversations/newtopic;_ylc=3DX3oDMTJlMjVhczlxBF9TAzk3MzU5NzE0BGdycElkAzQ5O=
TkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwNmdHIEc2xrA250cGMEc3RpbWUDMTQ4NjUxMDk5=
NQ--" style=3D"text-decoration: none; color: #2D50FD">Start a New Topic</a>
          </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;color: #2D50FD;" >
                            <a href=3D"https://groups.yahoo.com/neo/groups/=
ocaml_beginners/conversations/topics/14758;_ylc=3DX3oDMTM2YjYwa2FuBF9TAzk3M=
zU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BG1zZ0lkAzE0NzU5BHNlYwNm=
dHIEc2xrA3Z0cGMEc3RpbWUDMTQ4NjUxMDk5NQR0cGNJZAMxNDc1OA--" style=3D"text-dec=
oration: none; color: #2D50FD;">Messages in this topic</a>
                (2)
                      </td>
        </tr>
      </tbody>
    </table>

=20=20=20=20=20=20=20=20
<div id=3D"megaphoneModule">
            <hr style=3D"height:2px ; border-width:0; color:#E3E3E3; backgr=
ound-color:#E3E3E3;">
        <div>
	     <div class=3D"stream" style=3D"margin-bottom:10px;">
        <div style=3D"background-color:white;">
            <div class=3D"sn-img" style=3D"display:inline;"><img name=3D"tn=
_file" style=3D"padding:0px 10px;vertical-align:top;margin-top:5px;" src=3D=
"https://s.yimg.com/ru/static/images/yg/img/megaphone/1464031581_phpFA8bON"=
 height=3D"82" width=3D"82"></div>
            <div class=3D"mod-txt" style=3D"display:inline-block;">
                <a rel=3D"nofollow" name=3D"sub_url" target=3D"_blank" href=
=3D"https://yho.com/1wwmgg" style=3D"color:#0000FF;display:block;margin-lef=
t:5px;text-decoration:none;"><span style=3D"font-size:15px;">Have you tried=
 the highest rated email app?</span></a>
                <div style=3D"max-width:530px;padding:2px 5px;">With 4.5 st=
ars in iTunes, the Yahoo Mail app is the highest rated email app on the mar=
ket. 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 1000G=
B of free cloud storage.</div>
            </div>
        </div>
    </div>        </div>=20=20
=20=20=20=20=20
    <hr style=3D"height:2px ; border-width:0; color:#E3E3E3; background-col=
or:#E3E3E3;">
</div>

<!------- Start Nav Bar ------>


    <div id=3D"ygrp-grfd" style=3D"font-family: Verdana; font-size: 12px; p=
adding: 15px 0;">
=20=20=20=20=20=20
<!-- |**|begin egp html banner|**| -->

      Archives up to December 31, 2011 are also downloadable at <a href=3D"=
http://www.connettivo.net/cntprojects/ocaml_beginners">http://www.connettiv=
o.net/cntprojects/ocaml_beginners</a><BR>
The archives of the very official ocaml list (the seniors' one) can be foun=
d at <a href=3D"http://caml.inria.fr">http://caml.inria.fr</a><BR>
Attachments are banned and you're asked to be polite, avoid flames etc.    =
=20=20
<!-- |**|end egp html banner|**| -->

    </div>
=20=20

=20

<!-- |**|begin egp html banner|**| -->
<div id=3D"ygrp-vital" style=3D"background-color: #f2f2f2; font-family: Ver=
dana; font-size: 10px; margin-bottom: 10px; padding: 10px;">

    <span id=3D"vithd" style=3D"font-weight: bold; color: #333; text-transf=
orm: uppercase; "><a href=3D"https://groups.yahoo.com/neo/groups/ocaml_begi=
nners/info;_ylc=3DX3oDMTJldWNoMGZtBF9TAzk3MzU5NzE0BGdycElkAzQ5OTkxOTQEZ3Jwc=
3BJZAMxNzA1MDA2NzY0BHNlYwN2dGwEc2xrA3ZnaHAEc3RpbWUDMTQ4NjUxMDk5NQ--" style=
=3D"text-decoration: none;">Visit Your Group</a></span>

     <ul style=3D"list-style-type: none; margin: 0; padding: 0; display: in=
line;">
                                                    </ul>
  </div>


<div id=3D"ft" style=3D"font-family: Arial; font-size: 11px; margin-top: 5p=
x; padding: 0 2px 0 0; clear: both;">
  <a href=3D"https://groups.yahoo.com/neo;_ylc=3DX3oDMTJkbGtrM3U3BF9TAzk3ND=
c2NTkwBGdycElkAzQ5OTkxOTQEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwNmdHIEc2xrA2dmcARzd=
GltZQMxNDg2NTEwOTk2" style=3D"float: left;"><img src=3D"http://l.yimg.com/r=
u/static/images/yg/img/email/new_logo/logo-groups-137x15.png" height=3D"15"=
 width=3D"137" alt=3D"Yahoo! Groups" style=3D"border: 0;"/></a>
  <div style=3D"color: #747575; float: right;"> &bull; <a href=3D"https://i=
nfo.yahoo.com/privacy/us/yahoo/groups/details.html" style=3D"text-decoratio=
n: none;">Privacy</a> &bull; <a href=3D"mailto:ocaml_beginners-unsubscribe@=
yahoogroups.com?subject=3DUnsubscribe" style=3D"text-decoration: none;">Uns=
ubscribe</a> &bull; <a href=3D"https://info.yahoo.com/legal/us/yahoo/utos/t=
erms/" style=3D"text-decoration: none;">Terms of Use</a> </div>
</div>
<br>

<!-- |**|end egp html banner|**| -->

  </div> <!-- ygrp-msg -->

=20
  <!-- Sponsor -->
  <!-- |**|begin egp html banner|**| -->
  <div id=3D"ygrp-sponsor" style=3D"width:160px; float:right; clear:none; m=
argin:0 0 25px 0; background: #fff;">

<!-- Start Recommendations -->
<div id=3D"ygrp-reco">
     </div>
<!-- End Recommendations -->



  </div>   <!-- |**|end egp html banner|**| -->

  <div style=3D"clear:both; color: #FFF; font-size:1px;">.</div>
</div>

  <img src=3D"http://geo.yahoo.com/serv?s=3D97359714/grpId=3D4999194/grpspI=
d=3D1705006764/msgId=3D14759/stime=3D1486510995" width=3D"1" height=3D"1"> =
<br>

<img src=3D"http://y.analytics.yahoo.com/fpc.pl?ywarid=3D515FB27823A7407E&a=
=3D10001310322279&js=3Dno&resp=3Dimg&cf12=3DCP" width=3D"1" height=3D"1">=20

<div style=3D"color: #fff; height: 0;">__,_._,___</div>
<!--~-|**|PrettyHtmlEnd|**|-~-->

</body>

<!--~-|**|PrettyHtmlStart|**|-~-->
<head>
  <style type=3D"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;
  }
=20=20
  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.fi=
le-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;
  }=20

  #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;=20
  }=20
  -->
  </style>
</head>

<!--~-|**|PrettyHtmlEnd|**|-~-->
</html>
<!-- end group email -->


--001a114561aec8b6390547f94f3f--