<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEMERHoyfSp7ImA9WhBbF0g.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917</id><updated>2013-05-16T20:00:05.495-05:00</updated><category term="ruby" /><category term="linux" /><category term="theory" /><category term="math" /><category term="OpenAM" /><category term="active directory" /><category term="emacs" /><category term="scala" /><category term="goodreads" /><category term="java" /><category term="authentication" /><category term="REST" /><category term="books" /><category term="vmware" /><category term="data structure" /><category term="comics" /><category term="random" /><category term="quote" /><category term="Dijkstra" /><category term="continuations" /><category term="notation" /><category term="lisp" /><category term="protocols" /><category term="conference" /><category term="http" /><category term="SAML" /><category term="tip" /><category term="electronics" /><category term="software development" /><category term="c" /><category term="yeti" /><category term="job" /><category term="osgi" /><category term="ldap" /><category term="python" /><category term="shell" /><category term="coq" /><category term="unix" /><category term="haskell" /><category term="link" /><category term="toy problems" /><category term="eclipse virgo" /><category term="programming language" /><category term="c++" /><category term="Knuth" /><category term="naming" /><category term="rust" /><category term="system administration" /><title>Maniagnosis</title><subtitle type="html">Not devoured by plague-bearing zombies!</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://maniagnosis.crsr.net/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>214</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/crsr/nOWs" /><feedburner:info uri="crsr/nows" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>crsr/nOWs</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;CEMERHs7fip7ImA9WhBbF0g.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-5487758688062567476</id><published>2013-05-16T20:00:00.000-05:00</published><updated>2013-05-16T20:00:05.506-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-16T20:00:05.506-05:00</app:edited><title>An apology</title><content type="html">&lt;p&gt;If you have been viewing this blog recently and have been redirected to some advertisement site like search.goodcarquotes, or had a pop-up, or seen the Clicksor ads in the left bar, I would like to apologize. I had noticed them myself before, and finally took the time to track them down. It seems the Sociable gadget (that showed submit-this-page-to-various-social-networking-sites buttons) is &lt;i&gt;bad&lt;/i&gt;. I have removed it, and I hope I've cleaned up the situation.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="http://productforums.google.com/d/msg/blogger/0RNrVv3CBoY/wqdPOCz2nO0J"&gt;Nitecruzr&lt;/a&gt; on the Google product forums for the answer. (Note that the specific advice is only applicable to my layout.) For reference, see &lt;a href="http://blogging.nitecruzr.net/2013/04/blogger-blogs-being-hijacked-by.html"&gt;Blogger Blogs Being Hijacked By The Sociable Gadget&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/OwFu5Lw6qv0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/5487758688062567476/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=5487758688062567476" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/5487758688062567476?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/5487758688062567476?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/OwFu5Lw6qv0/an-apology.html" title="An apology" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/05/an-apology.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8NSXo7fSp7ImA9WhBbF08.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-7899654676284561801</id><published>2013-05-16T12:04:00.000-05:00</published><updated>2013-05-16T12:04:58.405-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-16T12:04:58.405-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quote" /><title>Quote o' the day: Do what the moody guy on the Ducati does</title><content type="html">&lt;p&gt;In a sub-thread on &lt;a href="http://www.reddit.com/r/programming/comments/1eeoqu/android_studio/"&gt;Reddit&lt;/a&gt; about the advantages of IntelliJ vs. Eclipse, Moerderhai &lt;a href="http://www.reddit.com/r/programming/comments/1eeoqu/android_studio/c9zu67g"&gt;wrote&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;
...So I tried this Intellij thing that the moody guy who rode a Ducati really liked....
&lt;/blockquote&gt;

&lt;p&gt;Moerderhai was then enlightened, he found a chickadee that laid golden eggs, rainbows and unicorns began wandering through his cubicle, and so on.&lt;/p&gt;

&lt;p&gt;(I don't know why I found this amusing.)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/d1z9y6YZ5xg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/7899654676284561801/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=7899654676284561801" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/7899654676284561801?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/7899654676284561801?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/d1z9y6YZ5xg/quote-o-day-do-what-moody-guy-on-ducati.html" title="Quote o' the day: Do what the moody guy on the Ducati does" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/05/quote-o-day-do-what-moody-guy-on-ducati.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAGRnc5eyp7ImA9WhBUFUw.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-6416133798806824721</id><published>2013-05-02T11:05:00.001-05:00</published><updated>2013-05-02T11:05:27.923-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-02T11:05:27.923-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="link" /><title>Link o' the day: A flashback</title><content type="html">&lt;p&gt;I ran across this recently. Apparently, Larry Loucks passed away back in 2006.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Computer Business Review&lt;/i&gt;, June 23, 1995: &lt;a href="http://www.cbronline.com/news/ibm_shifts_emphasis_of_work_on_microkernel"&gt;IBM SHIFTS EMPHASIS OF WORK ON MICROKERNEL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've got no idea what "Instead, it has been prototyped further down in the kernel, where performance gains of up to 1,000 times have apparently been achieved" is supposed to mean, and the IBM microkernel was hardly a clean-room effort; it was based on the Mach kernel from CMU. But still, I was there! That's where I spent a formative year or so of my life.&lt;/p&gt;

&lt;p&gt;And the performance of the IBM microkernel was really, really horrible.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/KrvS-ZzHiXg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/6416133798806824721/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=6416133798806824721" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/6416133798806824721?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/6416133798806824721?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/KrvS-ZzHiXg/link-o-day-flashback.html" title="Link o' the day: A flashback" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/05/link-o-day-flashback.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEABRX85cSp7ImA9WhBUEk0.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-3162941031592474752</id><published>2013-04-28T21:32:00.000-05:00</published><updated>2013-04-28T21:32:34.129-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-28T21:32:34.129-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software development" /><category scheme="http://www.blogger.com/atom/ns#" term="link" /><title>Link o' the day: Brian Kernighan on the Elements of Programming Style</title><content type="html">&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Brian_Kernighan"&gt;Brian Kernighan&lt;/a&gt;, co-creator of &lt;a href="http://en.wikipedia.org/wiki/AMPL"&gt;AMPL&lt;/a&gt;, gave a talk on the &lt;a href="http://video.ias.edu/PiTP2009-Kernighan"&gt;Elements of Programming Style&lt;/a&gt; in 2009 at the Institute for Advanced Study. The hour-long video is well worth a watch, although you should beware of the fire alarm at about 58 minutes.&lt;/p&gt;

&lt;p&gt;Kernighan, who now teaches at Princeton, continues the format of the original &lt;a href="http://en.wikipedia.org/wiki/The_Elements_of_Programming_Style"&gt;Elements of Programming Style&lt;/a&gt; by examining unsavory code found in the wild, either in programming textbooks or real-life software, but with up-to-date examples. Among the other, less interesting, points, at about 11:48 bwk indicates that he does not know how &lt;a href="http://linux.die.net/man/3/strpbrk"&gt;strpbrk&lt;/a&gt; should be pronounced.&lt;/p&gt;

&lt;p&gt;Does anyone reading this know what C (at 28:00) and C++ (43:45) books he is talking about? Those examples are &lt;i&gt;horrible&lt;/i&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/k2Rbk1K8iYA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/3162941031592474752/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=3162941031592474752" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/3162941031592474752?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/3162941031592474752?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/k2Rbk1K8iYA/link-o-day-brian-kernighan-on-elements.html" title="Link o' the day: Brian Kernighan on the Elements of Programming Style" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/04/link-o-day-brian-kernighan-on-elements.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQHSHo9eyp7ImA9WhBUE0g.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-8945799416644322443</id><published>2013-04-26T18:32:00.000-05:00</published><updated>2013-04-30T15:22:19.463-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T15:22:19.463-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Operator overloading in Rust</title><content type="html">&lt;p&gt;&lt;a href="http://www.rust-lang.org/"&gt;Rust&lt;/a&gt; offers several features that may make frustrated C++ programmers feel more at home. One of those features is operator overloading, for at least some common operators. The technique of overloading operators in Rust is handled through traits: the &lt;a href="http://static.rust-lang.org/doc/0.6/rust.html"&gt;Rust manual&lt;/a&gt; describes overloading by saying, "[arithmetic operator] expressions are syntactic sugar for calls to built-in traits, defined in the core::ops module of the core library. This means that arithmetic operators can be overridden for user-defined types." So, how does one use these built-in traits?&lt;/p&gt;

&lt;p&gt;Let's say you want to use complex numbers in your code, because you are the kind of person who knows what complex numbers are good for and can use them in a safe and appropriately sanitary fashion. &lt;a href="http://en.wikipedia.org/wiki/Complex_number"&gt;Complex numbers&lt;/a&gt;, for those of us who do not know what they are good for and probably cannot use a spatula in a safe and sanitary manner, are an extension of more commonly seen sets of numbers such as integers and real numbers, and pair a real number and an imaginary number. An &lt;a href="http://en.wikipedia.org/wiki/Imaginary_number"&gt;imaginary number&lt;/a&gt;, to back up a bit, is a multiple of a number \(i\) whose square is -1, so a complex number is expressible as \(a + bi\), where \(a\) is the real component and \(b\) is the imaginary component, multiplied by \(i\), the &lt;a href="http://en.wikipedia.org/wiki/Imaginary_unit"&gt;imaginary unit&lt;/a&gt;. The complex number system provides at least one root for every polynomial expression in much the same way that real numbers provide a value for every division, unlike the integers. Or at least that is the impression that Wikipedia gives me. Thank you, great Wiki!&lt;/p&gt;

&lt;p&gt;In any case, this is what a complex number looks like in Rust, at least according to me.&lt;/p&gt;

&lt;pre&gt;
struct Complex {
    r : float,
    j : float
}
&lt;/pre&gt;

&lt;p&gt;(In the code, \(i\), the traditional notation for the imaginary unit, is replaced by j by suggestion of &lt;a href="http://www.reddit.com/r/programming/comments/1dcbos/operator_overloading_in_rust/c9p8hf9"&gt;englabenny&lt;/a&gt; and &lt;a href="http://www.reddit.com/r/programming/comments/1dcbos/operator_overloading_in_rust/c9pk5rv"&gt;dfjkfskjhfshdfjhsdjl&lt;/a&gt; on &lt;a href="http://www.reddit.com/r/programming/comments/1dcbos/operator_overloading_in_rust/"&gt;reddit&lt;/a&gt;, because "1i" is the Rust notation for 1 as an int and because "i" is associated with current in various disciplines that commonly use complex numbers.)&lt;/p&gt;

&lt;p&gt;This is a structure containing two fields, the real component and the imaginary component. &lt;b&gt;float&lt;/b&gt; is the Rust machine-dependent floating point type, and represents the largest floating point type preferred on the target hardware. (Alternatively, &lt;b&gt;f32&lt;/b&gt; and &lt;b&gt;f64&lt;/b&gt; are the 32- and 64-bit machine independent floating point types.)&lt;/p&gt;

&lt;p&gt;To overload the operator + for complex numbers, just provide an implementation of the &lt;b&gt;Add&lt;/b&gt; trait:&lt;/p&gt;

&lt;pre&gt;
impl Add&amp;lt;Complex,Complex&gt; for Complex {
    fn add(&amp;self, rhs: &amp;Complex) -&gt; Complex {
        Complex {
            r : self.r + rhs.r,
            j : self.j + rhs.j
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;The &lt;b&gt;Add&lt;/b&gt; trait contains one method, &lt;b&gt;add&lt;/b&gt;, that performs the operation. To unpack the impl line, implementing &lt;b&gt;Add&lt;/b&gt;&amp;lt;X,Y&gt; &lt;b&gt;for&lt;/b&gt; Z for types X, Y, and Z would provide an implementation of the operation where the left-hand side was a Z (the receiver of the method and the type for which the trait is being implemented), the right-hand side would be an X (the argument to the method), and the result would be a Y. This implementation allows two complex numbers to be added, producing a new complex number.&lt;/p&gt;

&lt;p&gt;One thing I would like to be able to do is to provide multiple implementations of the &lt;b&gt;Add&lt;/b&gt; trait, such as:&lt;/p&gt;

&lt;pre&gt;
// impl Add&amp;lt;float,Complex&gt; for Complex {
//     fn add(&amp;self, rhs : &amp;float) -&gt; Complex {
//         Complex { r : self.r + *rhs, j : self.j }
//     }
// }
&lt;/pre&gt;

&lt;p&gt;This implementation would allow floating point numbers as the right-hand side, producing a complex result. Unfortunately, the current Rust trait implementation does not allow that, complaining about conflicting operations.&lt;/p&gt;

&lt;pre&gt;
complex.rs:52:0: 56:1 error: conflicting implementations for a trait
...
complex.rs:24:0: 28:1 error: conflicting implementations for a trait
...
complex.rs:81:12: 81:17 error: multiple applicable methods in scope
...
&lt;/pre&gt;

&lt;p&gt;Something to look forward to in future releases.&lt;/p&gt;

&lt;p&gt;With that said, the following code now works and produces the expected results:&lt;/p&gt;

&lt;pre&gt;
    let x = Complex { r : 1.0, j : 0.0 };
    let y = Complex { r : 3.0, j : 0.0 };
    let z = x + y;
&lt;/pre&gt;

&lt;p&gt;Two further examples implement subtraction and multiplication for Complex values.&lt;/p&gt;

&lt;pre&gt;
impl Sub&amp;lt;Complex,Complex&gt; for Complex {
    fn sub(&amp;self, rhs : &amp;Complex) -&gt; Complex {
        Complex { r : self.r - rhs.r, j : self.j - rhs.j }
    }
}

impl Mul&amp;lt;Complex,Complex&gt; for Complex {
    fn mul(&amp;self, rhs : &amp;Complex) -&gt; Complex {
        Complex {
            r : (self.r * rhs.r) - (self.j * rhs.j),
            j : (self.r * rhs.j) + (self.j * rhs.r)
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;Isn't that just &lt;a href="http://en.wikipedia.org/wiki/Marvin_the_Martian#History"&gt;lovely&lt;/a&gt;, hmm?&lt;/p&gt;

&lt;p&gt;The operators which can be overloaded, as of Rust 0.6, are:&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;th style="text-align:center;"&gt;Operator&lt;/th&gt;&lt;th style="text-align:center;"&gt;Trait&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th colspan="2" style="text-align:center;"&gt;Arithmetic&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;+&lt;/td&gt;&lt;td&gt;core::ops::Add&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;core::ops::Sub&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;core::ops::Mul&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/&lt;/td&gt;&lt;td&gt;core::ops::Div&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;%&lt;/td&gt;&lt;td&gt;core::ops::Modulo&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;- (unary negation)&lt;/td&gt;&lt;td&gt;core::ops::Neg&amp;lt;Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th colspan="2" style="text-align:center;"&gt;Bitwise&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;&lt;/td&gt;&lt;td&gt;core::ops::BitAnd&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;|&lt;/td&gt;&lt;td&gt;core::ops::BitOr&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;^ (exclusive or)&lt;/td&gt;&lt;td&gt;core::ops::BitXor&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;lt;&amp;lt; (shift left)&lt;/td&gt;&lt;td&gt;core::ops::Shl&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&gt;&gt; (shift right)&lt;/td&gt;&lt;td&gt;core::ops::Shr&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th colspan="2" style="text-align:center;"&gt;Comparison&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;==&lt;/td&gt;&lt;td&gt;core::cmp::Eq&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;!=&lt;/td&gt;&lt;td&gt;core::cmp::Eq&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;lt;&lt;/td&gt;&lt;td&gt;core::cmp::Ord&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&gt;&lt;/td&gt;&lt;td&gt;core::cmp::Ord&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;lt;=&lt;/td&gt;&lt;td&gt;core::cmp::Ord&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&gt;=&lt;/td&gt;&lt;td&gt;core::cmp::Ord&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th colspan="2" style="text-align:center;"&gt;Miscellaneous&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;! (Boolean negation)&lt;/td&gt;&lt;td&gt;core::ops::Not&amp;lt;Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;i&gt;a&lt;/i&gt;[&lt;i&gt;i&lt;/i&gt;] (indexing)&lt;/td&gt;&lt;td&gt;core::ops::Index&amp;lt;RHS,Result&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;In order to preserve sanity, Rust limits operator overloading. As &lt;a href="http://www.reddit.com/r/programming/comments/1dcbos/operator_overloading_in_rust/c9pkkla"&gt;kibwen&lt;/a&gt; pointed out in the reddit discussion, there are &lt;a href="http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/"&gt;restrictions&lt;/a&gt; on where traits, types, and the implementations of traits for types can legitimately appear. Specifically, the implementation must be in the same &lt;a href="http://static.rust-lang.org/doc/0.6/rust.html#crates-and-source-files"&gt;crate&lt;/a&gt; as either the type or the trait. kibwen writes,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now note that the overloading traits are defined in libcore, which is shipped with the Rust compiler.&lt;/p&gt;

&lt;p&gt;The implication then is that it is only possible to overload operators on types that you've defined yourself. You never have to worry about library A attempting distant overloads on types from library B; this also means that you never have to worry about libraries changing what 2+2 means.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point, I must note that operator overloading, even with Rust's limits on it, is not something to be used without considerable thought. If you misuse overloading, doing something like C++'s 'cout &lt;&lt; "hello world"', a &lt;a href="http://www.reddit.com/r/programming/comments/1dcbos/operator_overloading_in_rust/c9poj64"&gt;Rust developer&lt;/a&gt; will find you. And &lt;a href="http://en.wikipedia.org/wiki/My_Little_Duckaroo#Summary"&gt;Fix. Your. Little. Red. Wagon&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Going further with complex numbers&lt;/h2&gt;

&lt;p&gt;Complex numbers have two specialized operations that are useful to me here: conjugation, which negates the imaginary component, and magnitude, which computes the distance of a complex number from the origin of the complex number plane. (The magnitude is the closest I can come to a meaningful way of down-converting from a complex number to a floating value.)&lt;/p&gt;

&lt;pre&gt;
impl Complex {
    fn conjugate(&amp;self) -&gt; Complex { Complex { r : self.r, j : -self.j } }
    fn magnitude(&amp;self) -&gt; float { float::sqrt( self.r * self.r + self.j * self.j ) }
}
&lt;/pre&gt;

&lt;p&gt;This implementation provides conjugate and magnitude methods for the Complex structure; think of it as the implementation of an anonymous trait. One thing we need the conjugate method for is implementing division for complex numbers:&lt;/p&gt;

&lt;pre&gt;
impl Div&amp;lt;Complex,Complex&gt; for Complex {
    fn div(&amp;self, rhs : &amp;Complex) -&gt; Complex {
        let rhs_conj = rhs.conjugate();
        let num      = self * rhs_conj;
        let denom    = rhs * rhs_conj;
        Complex {
            r : (num.r / denom.r),
            j : (num.i / denom.r)
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;Speaking of traits, &lt;b&gt;ToStr&lt;/b&gt; is a trait supported by most Rust types, converting a value to a string.&lt;/p&gt;

&lt;pre&gt;
impl ToStr for Complex {
    fn to_str(&amp;self) -&gt; ~str { fmt!("(%f + %fi)", self.r, self. i) }
}
&lt;/pre&gt;

&lt;p&gt;For Complex, &lt;b&gt;to_str&lt;/b&gt; will produce a string of the form "(a + bi)". One further thing that I would like to be able to do is to convert other values, such as &lt;b&gt;float&lt;/b&gt;'s into Complex numbers.&lt;/p&gt;

&lt;pre&gt;
trait ToComplex { fn to_complex(&amp;self) -&gt; Complex; }

impl ToComplex for float {
    fn to_complex(&amp;self) -&gt; Complex { Complex { r : *self, j : 0.0f } }
}
&lt;/pre&gt;

&lt;p&gt;That trait and implementation adds a &lt;b&gt;to_complex&lt;/b&gt; method to any &lt;b&gt;float&lt;/b&gt; value, such as &lt;code&gt;3.0f.to_complex()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is a standard trait for converting among numeric types in Rust, &lt;b&gt;NumCast&lt;/b&gt;. This is the implementation of it for Complex numbers:&lt;/p&gt;

&lt;pre&gt;
impl NumCast for Complex {
    fn from&amp;lt;N:NumCast&gt;(n: N) -&gt; Complex { n.to_float().to_complex() }

    fn to_u8(&amp;self)    -&gt; u8    { self.magnitude() as u8    }
    fn to_u16(&amp;self)   -&gt; u16   { self.magnitude() as u16   }
    fn to_u32(&amp;self)   -&gt; u32   { self.magnitude() as u32   }
    fn to_u64(&amp;self)   -&gt; u64   { self.magnitude() as u64   }
    fn to_uint(&amp;self)  -&gt; uint  { self.magnitude() as uint  }

    fn to_i8(&amp;self)    -&gt; i8    { self.magnitude() as i8    }
    fn to_i16(&amp;self)   -&gt; i16   { self.magnitude() as i16   }
    fn to_i32(&amp;self)   -&gt; i32   { self.magnitude() as i32   }
    fn to_i64(&amp;self)   -&gt; i64   { self.magnitude() as i64   }
    fn to_int(&amp;self)   -&gt; int   { self.magnitude() as int   }

    fn to_f32(&amp;self)   -&gt; f32   { self.magnitude() as f32   }
    fn to_f64(&amp;self)   -&gt; f64   { self.magnitude() as f64   }
    fn to_float(&amp;self) -&gt; float { self.magnitude()          }
}
&lt;/pre&gt;

&lt;p&gt;With that addition, I can write the following &lt;b&gt;main&lt;/b&gt;:&lt;/p&gt;

&lt;pre&gt;
fn main() {
    let x = Complex { r : 1.0, j : 0.0 };
    let y = Complex { r : 3.0, j : 0.0 };
    let z = x + y;
    let w = NumCast::from(2);
    println(( y + 3.0f.to_complex()   ).to_str());
    println(( x * NumCast::from(3.0f) ).to_str());
    println(( x * NumCast::from(4)    ).to_str());
    println(( z / w                   ).to_str());

    let n = Complex { r : 0.0, j : 1.0 };
    println(( n * n                   ).to_str());
}
&lt;/pre&gt;

&lt;p&gt;Which produces the following output:&lt;/p&gt;

&lt;pre&gt;
(6 + 0i)
(3 + 0i)
(4 + 0i)
(2 + 0i)
(-1 + 0i)
&lt;/pre&gt;

&lt;p&gt;The source code for these examples in on &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/complex.rs"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would like to thank the commenters from Reddit, particularly englabenny, dfjkfskjhfshdfjhsdjl, and kibwen, for their help.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/Bn2hN6QF5o4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/8945799416644322443/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=8945799416644322443" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/8945799416644322443?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/8945799416644322443?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/Bn2hN6QF5o4/operator-overloading-in-rust.html" title="Operator overloading in Rust" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/04/operator-overloading-in-rust.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUEQXY_eSp7ImA9WhBVEUs.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-5648852344507446053</id><published>2013-04-16T20:30:00.000-05:00</published><updated>2013-04-16T20:30:00.841-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-16T20:30:00.841-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Letterpress cheating in Rust: Parallelism part 2</title><content type="html">&lt;p&gt;Last time I wrote, "Or, how to turn an 8 second runtime to a 27 second runtime by throwing a stack of CPU's at it", but I did not actually describe that case. It turns out that the second
option for parallelizing the anagram program is the way to do that. As a reminder, the second option is:&lt;/p&gt;

&lt;blockquote&gt;Have each of the \(N\) tasks get its own copy of the complete dictionary. The main task then sends each request computed from the input letters (30,000,000 queries, remember) to one of the tasks, which accumulates a subset of the anagram words and then communicates those back to the main task.&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors-tasks.rs"&gt;code&lt;/a&gt; for this version is somewhat similar to that for &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors-wide.rs"&gt;option 1&lt;/a&gt;, so rather than presenting the whole main function I am just showing the key bits.&lt;/p&gt;

&lt;p&gt;The first block creates the worker tasks and sets up streams to allow the master task to send requests.&lt;/p&gt;

&lt;pre&gt;
    let mut request_chans : ~[Chan&amp;lt;~[~[int]]&gt;] = ~[];
    for uint::range(0, width) |_| {
        let (request_port,request_chan) = stream();
        request_chans.push(request_chan);
        // Set up and start worker task
        let response_chan = response_chan.clone();
        do spawn {
            let (keys,values) = load_dictionary();
            response_chan.send( search(keys, values, &amp;request_port) );
        }
    }
&lt;/pre&gt;

As a reminder, Rust tasks communicate only by sending and receiving messages; a &lt;b&gt;Port&lt;/b&gt; is the sending side and a &lt;b&gt;Chan&lt;/b&gt; is the receiving side. In this code, the main task creates an empty vector of &lt;b&gt;Chan&lt;/b&gt;'s and enters a loop where it&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creates a stream,&lt;/li&gt;
&lt;li&gt;stores the Chan for the main task's use,&lt;/li&gt;
&lt;li&gt;duplicates the Chan used to report results from the worker task to the master, and&lt;/li&gt;
&lt;li&gt;finally spawns a worker task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The worker task loads a copy of the &lt;b&gt;keys&lt;/b&gt; and &lt;b&gt;values&lt;/b&gt; vectors (remember that the "vectors" version of the program uses binary search rather than a hash table to store and look-up matching letter sequences), and calls a &lt;b&gt;search&lt;/b&gt; function to perform the useful work. When done, the results are returned to the master task via the &lt;b&gt;response_chan&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;The search function looks like this:&lt;/p&gt;

&lt;pre&gt;
fn search(keys         : &amp;[~[int]],
          values       : &amp;[~[~str]],
          request_port : &amp;Port&amp;lt;~[~[int]]&gt;) -&gt; ~LinearSet&amp;lt;~str&gt; {
    let klen    = keys.len();
    let mut set = ~LinearSet::new();
    loop {
        let key_set = request_port.recv();
        if key_set.len() == 0 { break; }
        for key_set.each |key| {
            let j = bisect::bisect_left_ref(keys, key, 0, klen);
            if j &lt; klen &amp;&amp; keys[j] == *key {
                for values[j].each |&amp;word| { set.insert(copy word); }
            }
        }
    }
    return set;
}
&lt;/pre&gt;

&lt;p&gt;Notice that the type of &lt;b&gt;request_port&lt;/b&gt; is a borrowed pointer to &lt;b&gt;Port&amp;lt;~[~[int]]&gt;&lt;/b&gt;: a &lt;b&gt;Port&lt;/b&gt; on which the code can receive vectors of vectors of ints. The reason for the levels of vectors is simple: the key used for each look-up is a vector of ints, created from a string of letters. Unfortunately, sending each key individually (all 33,000,000 of them) would result in an enormous amount of communications overhead; this code receives a collection of keys (the badly named &lt;b&gt;key_set&lt;/b&gt;) to look up at once. The master task signals that the worker should complete by sending an empty &lt;b&gt;key_set&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;The master task hands out requests to the workers with the following code:&lt;/p&gt;

&lt;pre&gt;
    let mut t = 0;
    let mut key_set = ~[];
    for uint::range(2,letters.len() + 1) |i| {
        for combinations::each_combination(letters,i) |combo| {
            key_set.push( vec::from_slice(combo) );
            if key_set.len() &gt;= depth {
                let mut ks = ~[];
                ks &lt;-&gt; key_set;
                request_chans[t].send(ks);
                t = (t + 1) % width;
            }
        }
    }
    if !key_set.is_empty() { request_chans[t].send(key_set); }
    for request_chans.each |chan| { chan.send(~[]) };
&lt;/pre&gt;

&lt;p&gt;The variable &lt;b&gt;t&lt;/b&gt; is used to identify which worker should receive a request; this code allocates the work round-robin style. It also accumulates &lt;b&gt;depth&lt;/b&gt; keys into each request.&lt;/p&gt;

&lt;p&gt;The dance in the innermost block is needed to avoid having &lt;b&gt;key_set&lt;/b&gt; losing its value on each iteration. The &lt;b&gt;send&lt;/b&gt; call transfers ownership of the message to the receiving task, so &lt;b&gt;chan.send(key_set)&lt;/b&gt; would leave &lt;b&gt;key_set&lt;/b&gt; without any meaningful value. This code instead creates a new variable, &lt;b&gt;ks&lt;/b&gt;, containing an empty vector. &lt;b&gt;ks&lt;/b&gt; and &lt;b&gt;key_set&lt;/b&gt; then swap values, resetting &lt;b&gt;key_set&lt;/b&gt; to the empty vector, and &lt;b&gt;ks&lt;/b&gt; is used to send the request to the worker&amp;mdash;&lt;b&gt;ks&lt;/b&gt; is not used again, so there is no problem with it losing ownership while &lt;b&gt;key_set&lt;/b&gt; &lt;i&gt;is&lt;/i&gt; used again, on the next iteration.&lt;/p&gt;

&lt;p&gt;The second-to-last line sends any remaining keys to the next worker thread, and the final line sends the empty request to inform the workers that no further requests will be made.&lt;/p&gt;

&lt;p&gt;How well does this work?&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;th&gt;Language&lt;/th&gt;
    &lt;th&gt;Program&lt;/th&gt;
    &lt;th&gt;Time (sec)&lt;/th&gt;
    &lt;th&gt;Speedup&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Python &lt;/td&gt;&lt;td&gt; alternatives/presser_one.py   &lt;/td&gt;&lt;td&gt; 49.12    &lt;/td&gt;&lt;td&gt; 1  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Rust   &lt;/td&gt;&lt;td&gt; anagrams-vectors-tasks        &lt;/td&gt;&lt;td&gt; 27.13    &lt;/td&gt;&lt;td&gt; 2  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Python &lt;/td&gt;&lt;td&gt; alternatives/presser_two.py   &lt;/td&gt;&lt;td&gt; 12.84    &lt;/td&gt;&lt;td&gt; 4  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Rust   &lt;/td&gt;&lt;td&gt; anagrams-vectors-wide         &lt;/td&gt;&lt;td&gt; 11.75    &lt;/td&gt;&lt;td&gt; 4  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Rust   &lt;/td&gt;&lt;td&gt; anagrams-hashmap-wide         &lt;/td&gt;&lt;td&gt;  9.38    &lt;/td&gt;&lt;td&gt; 5  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; C      &lt;/td&gt;&lt;td&gt; alternatives/anagrams-vectors &lt;/td&gt;&lt;td&gt;  8.05    &lt;/td&gt;&lt;td&gt; 6  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Rust   &lt;/td&gt;&lt;td&gt; anagrams-vectors              &lt;/td&gt;&lt;td&gt;  7.97    &lt;/td&gt;&lt;td&gt; 6  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Rust   &lt;/td&gt;&lt;td&gt; anagrams-hashmap              &lt;/td&gt;&lt;td&gt;  5.98    &lt;/td&gt;&lt;td&gt; 8  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Python &lt;/td&gt;&lt;td&gt; alternatives/presser_three.py &lt;/td&gt;&lt;td&gt;  5.94    &lt;/td&gt;&lt;td&gt; 8  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; C      &lt;/td&gt;&lt;td&gt; alternatives/anagrams-hash    &lt;/td&gt;&lt;td&gt;  0.94    &lt;/td&gt;&lt;td&gt; 52 &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The program here, &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors-tasks.rs"&gt;anagrams-vectors-tasks&lt;/a&gt;, takes about 27 seconds, making it the second-slowest of the current crop and much worse than the 8 seconds used by the sequential version of the same algorithm. Unlike the other parallel versions, anagrams-vectors-wide and anagrams-hashmap-wide, it also does not keep the CPU's busy; rather than seeing 100% utilization of five or six CPUs, I see  40 or 50%.&lt;/p&gt;

&lt;p&gt;I believe Rust's send and receive implement a rendezvous: if a sender is not waiting with a message, the receiver blocks until a sender comes along; if a receiver is not waiting, the sender blocks. This is good in some cases, where it makes some optimizations possible. For example, it is possible to avoid invoking the thread scheduler if the sending thread can change its execution context and continue as the receiving thread. On the other hand, a rendezvous is bad here, because after the master task assigns a group of keys to the last worker task, it wraps around to send the next request to the first worker and must wait until the first worker task is finished with the &lt;i&gt;previous&lt;/i&gt; group of keys, at which time that worker will call &lt;b&gt;recv&lt;/b&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/EUF-OYkLJ30" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/5648852344507446053/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=5648852344507446053" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/5648852344507446053?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/5648852344507446053?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/EUF-OYkLJ30/letterpress-cheating-in-rust.html" title="Letterpress cheating in Rust: Parallelism part 2" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/04/letterpress-cheating-in-rust.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AMQnwyfip7ImA9WhBWE0s.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-2285424256748013908</id><published>2013-04-07T16:23:00.000-05:00</published><updated>2013-04-07T16:23:03.296-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-07T16:23:03.296-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Letterpress cheating in Rust: Parallelism</title><content type="html">&lt;p&gt;&lt;b&gt;Or, how to turn an 8 second runtime to a 27 second runtime by throwing a stack of CPU's at it.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://maniagnosis.crsr.net/2013/02/exploring-rust.html"&gt;anagram&lt;/a&gt; &lt;a href="http://maniagnosis.crsr.net/2013/02/creating-letterpress-cheating-program.html"&gt;programs&lt;/a&gt; I have been using to explore Rust are CPU bound. They take command line arguments, read a file, do some number of seconds (or minutes) of computation, and print out a number. In other words, in modern terms, it is begging for parallelization&lt;sup&gt;&lt;a href="#f1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;After a little thought (very little, as will probably become obvious), there are two ways of doing it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Split the anagram dictionary into \(N\) non-overlapping segments and feed those to \(N\) tasks along with the input letters. (&lt;a href="http://static.rust-lang.org/doc/0.6/rust.html#tasks"&gt;Rust&lt;/a&gt; supports lightweight threads running under multiple CPU's, so-called "M:N threading".) Each task then runs all of the 30,000,000 queries implied by my standard input letters against its fragment of the dictionary, computing its subset of the anagram words as a LinearMap. Then each task communicates its result map back to the main thread, which accumulates the results and prints the final answer.&lt;/li&gt;

&lt;li&gt;Have each of the \(N\) tasks get its own copy of the complete dictionary. The main task then sends each request computed from the input letters (30,000,000 queries, remember) to one of the tasks, which accumulates a subset of the anagram words and then communicates those back to the main task.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll take a look at the first option here using, inexplicably, the &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors.rs"&gt;vector, binary search,&lt;/a&gt; version of the programs. Here's the &lt;b&gt;main&lt;/b&gt; function of the first:&lt;/p&gt;

&lt;pre&gt;
fn main() {
    let width = 6;

    let args = os::args();
    if args.len() &amp;lt; 2 { fail!(~"Usage: anagrams letters"); }
    let letters = get_letters(args[1]);

    let (response_port,response_chan)
        : (Port&amp;lt;~LinearSet&amp;lt;~str&gt;&gt;,Chan&amp;lt;~LinearSet&amp;lt;~str&gt;&gt;) = stream();
    let response_chan = SharedChan(response_chan);

    for load_dictionary(width).each |&amp;kv_pair{keys   : keys,
                                              values : values}| {
        let response_chan = response_chan.clone();
        let letters = copy letters;
        do spawn {
            let set = search(letters, keys, values);
            response_chan.send(set);
        }
    }

    let mut set = ~LinearSet::new();
    for uint::range(0,width) |_| {
        let res = response_port.recv();
        for res.each |&amp;word| { set.insert(word); }
    }
    println(fmt!("%u", set.len()));
}
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;width&lt;/b&gt; is the number of sub-tasks to spawn and the next three lines set up the input query letters. The next three lines build up &lt;b&gt;response_port&lt;/b&gt; and &lt;b&gt;response_chan&lt;/b&gt;, used to communicate the sub-task's results to the main task.&lt;/p&gt;

&lt;p&gt;The next block does the work of the program. The &lt;b&gt;load_dictionary&lt;/b&gt; function, in this program, reads the dictionary file and splits it into &lt;b&gt;width&lt;/b&gt; individual &lt;b&gt;keys&lt;/b&gt; and &lt;b&gt;values&lt;/b&gt; pairs of vectors. (I don't want to talk about the "&lt;b&gt;kv_pair&lt;/b&gt;" structure. Let's just pretend it didn't happen.) The next step is to set up each sub-task's copy of the &lt;b&gt;response_chan&lt;/b&gt; (via the call to &lt;b&gt;clone&lt;/b&gt;) and a copy of the input &lt;b&gt;letters&lt;/b&gt;. Then it calls &lt;b&gt;spawn&lt;/b&gt; with an anonymous function; &lt;b&gt;spawn&lt;/b&gt; executes the function in a separate task; that function here performs the 30,000,000 lookups and returns the resulting map.&lt;/p&gt;

&lt;p&gt;The reason that &lt;b&gt;letters&lt;/b&gt; has to be copied before calling &lt;b&gt;spawn&lt;/b&gt; is that it is an owned value and the new anonymous function will take ownership of it in the new task; subsequent tasks wouldn't be able to get a copy of &lt;b&gt;letters&lt;/b&gt;. Or, more correctly, the compiler will make whiney noises, since the type system is watching for things like that.&lt;/p&gt;

&lt;p&gt;How do the sub-tasks report their results back to the main task? That is the purpose of &lt;b&gt;response_port&lt;/b&gt; and &lt;b&gt;response_chan&lt;/b&gt;. Rust tasks communicate by sending messages, with &lt;b&gt;Chan&lt;/b&gt;'s being the sending end and &lt;b&gt;Port&lt;/b&gt;'s being the receiving end of the message stream.&lt;/p&gt;

&lt;p&gt;Creating that stream is handled by the second block of three lines, fundamentally by the call to &lt;b&gt;core::comms::stream&lt;/b&gt;. The basic stream contains messages from exactly one task, destined for exactly one other task. In order to send results from multiple sub-tasks, the &lt;b&gt;Chan&lt;/b&gt; end is wrapped in a &lt;b&gt;SharedChan&lt;/b&gt;, which adds the &lt;b&gt;clone&lt;/b&gt; method used further down. &lt;b&gt;clone&lt;/b&gt; duplicates the &lt;b&gt;SharedChan&lt;/b&gt;, allowing it to be used by multiple tasks to send messages to a single &lt;b&gt;Port&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Sending the result is handled by &lt;b&gt;response_chan.send(set)&lt;/b&gt;, where set is a &lt;b&gt;~LinearSet&amp;lt;~str&gt;&lt;/b&gt;; the important part is that set is an owned structure. Before the send, the sub-task owns it, and after the send, the main, receiving, task owns it. Receiving is handled by &lt;b&gt;response_port.recv()&lt;/b&gt;. The main task uses the received result to accumulate its own, complete, set of results for all tasks and prints out the size of the set.&lt;/p&gt;

&lt;p&gt;So, how well does this work?&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;th&gt; Program                    &lt;/th&gt;&lt;th&gt; Duration (secs) &lt;/th&gt;&lt;th&gt; Speedup &lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors-wide.rs"&gt;anagrams-vectors-wide&lt;/a&gt;         &lt;/td&gt;&lt;td&gt; 11.75    &lt;/td&gt;&lt;td&gt; 4  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-hashmap-wide.rs"&gt;anagrams-hashmap-wide&lt;/a&gt;         &lt;/td&gt;&lt;td&gt;  9.38    &lt;/td&gt;&lt;td&gt; 5  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors.rs"&gt;anagrams-vectors&lt;/a&gt;              &lt;/td&gt;&lt;td&gt;  7.97    &lt;/td&gt;&lt;td&gt; 6  &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-hashmap.rs"&gt;anagrams-hashmap&lt;/a&gt;              &lt;/td&gt;&lt;td&gt;  5.98    &lt;/td&gt;&lt;td&gt; 8  &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The program we've been discussing is &lt;b&gt;anagrams-vectors-wide&lt;/b&gt;; &lt;b&gt;anagrams-hashmap-wide&lt;/b&gt; is a &lt;b&gt;LinearMap&lt;/b&gt;-based version with identical structure. (Yeah, I don't get to name things.) &lt;b&gt;anagrams-vectors&lt;/b&gt; and &lt;b&gt;anagrams-hashmap&lt;/b&gt; are the serial versions. They're indeed faster; the speedup is a factor of the slowest version of the program, the first Python version. Interestingly, if you multiply the time taken by the serial version by 6, the number of parallel tasks, you get roughly the amount of user plus system CPU time taken by the parallel version. Anyway, the performance difference is almost certainly tasking overhead, although I have no idea what exactly is causing it at the moment. But more on that in the next post.&lt;/p&gt;

&lt;p&gt;&lt;a name="f1" id="f1"&gt;1.&lt;/a&gt; My $10 word of the day. I hope I spelled it right; it's not in my dictionary. It's also hard to pronounce.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/yYE7-pbKOoA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/2285424256748013908/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=2285424256748013908" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2285424256748013908?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2285424256748013908?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/yYE7-pbKOoA/letterpress-cheating-in-rust-parallelism.html" title="Letterpress cheating in Rust: Parallelism" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/04/letterpress-cheating-in-rust-parallelism.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4CQnY6fSp7ImA9WhBXFEU.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-1248615839482967824</id><published>2013-03-26T20:08:00.000-05:00</published><updated>2013-03-28T11:09:23.815-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-28T11:09:23.815-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="notation" /><category scheme="http://www.blogger.com/atom/ns#" term="haskell" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="data structure" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Creating a Letterpress cheating program in Rust: Traits</title><content type="html">&lt;p&gt;Ok, I'm not saying you would want to do this. But you could. That's all I want to get across. Just that you &lt;i&gt;could&lt;/i&gt; do this, if you really wanted to.&lt;/p&gt;

&lt;p&gt;What could you do? Let's say you are writing a &lt;a href="http://maniagnosis.crsr.net/2013/02/exploring-rust.html"&gt;Letterpress&lt;/a&gt; &lt;a href="http://maniagnosis.crsr.net/2013/02/rust-iterators.html"&gt;cheating&lt;/a&gt; &lt;a href="http://maniagnosis.crsr.net/2013/02/creating-letterpress-cheating-program.html"&gt;thingy&lt;/a&gt; and need a program to generate the anagram dictionary: a file that contains a list of sorted letters, followed by the word or words that are made from those letters:&lt;/p&gt;

&lt;pre&gt;
...
aabcdiinot abdication
aabcdkrsw backwards drawbacks
aabcdkrsy backyards
...
&lt;/pre&gt;

&lt;p&gt;One way would be to &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/mk_anadict.rs"&gt;just do it&lt;/a&gt;, which I've mentioned &lt;a href="http://maniagnosis.crsr.net/2013/02/exploring-rust.html"&gt;before&lt;/a&gt;. But that would hardly be any fun, right? How about we use (or overuse) &lt;i&gt;traits&lt;/i&gt;?&lt;/p&gt;

&lt;p&gt;Rust's &lt;a href="http://static.rust-lang.org/doc/tutorial.html#traits"&gt;traits&lt;/a&gt; are akin to Java interfaces or Haskell's type classes. &lt;a href="http://static.rust-lang.org/doc/rust.html#traits"&gt;Traits&lt;/a&gt; provide two things in Rust: a set of related functions (or "methods" in this case) which can be implemented for any suitable data structure, and as the Rust tutorial describes, a way to bound the type parameters of generic operations, limiting the types that can be arguments to the generic functions to those which implement the given trait as well as making the trait's methods available on the values of the generic type.&lt;/p&gt;

&lt;p&gt;The first thing the mk_anadict program does is to read the /usr/dict/words file and create a dictionary mapping sorted sequences of letters to a list of words that can be made from those letters. Here is a trait that describes that operation:&lt;/p&gt;

&lt;pre&gt;
trait DictReader {
    fn read_dict(&amp;self) -&gt; ~LinearMap&amp;lt;~str,~[~str]&gt;;
}
&lt;/pre&gt;

&lt;p&gt;That declaration says that an implementation of &lt;b&gt;DictReader&lt;/b&gt; provides a method, &lt;b&gt;read_dict&lt;/b&gt;, that takes no arguments (other than the object the method is invoked on) and returns a map from strings to vectors of strings. Now, I could provide a &lt;i&gt;sui generis&lt;/i&gt; &lt;a href="http://static.rust-lang.org/doc/rust.html#implementations"&gt;implementation&lt;/a&gt; of that trait, by creating a new type and defining an implementation on it, but that doesn't really show the power of traits. Instead, I wrote an implementation of the trait for an existing type, in effect adding the &lt;b&gt;read_dict&lt;/b&gt; method to the existing type:&lt;/p&gt;

&lt;pre&gt;
impl DictReader for Reader {

    fn read_dict(&amp;self) -&gt; ~LinearMap&amp;lt;~str,~[~str]&gt; {
        let mut map = ~LinearMap::new();
        for self.each_line |line| {
            let line = line.trim();
            let length = line.len();
            // Original is using pre-strip() line for comparisons
            if length &gt;= 2 &amp;&amp; length &lt; 19
                &amp;&amp; line.all(|ch| (char::is_ascii(ch)
                                  &amp;&amp; char::is_lowercase(ch))) {
                let mut chars = str::chars(line);
                std::sort::quick_sort(chars, |a,b| *a &lt;= *b);
                let key = str::from_chars(chars);

                // What I'd like to do:
                // map.find_or_insert(key, ~[]).push(line);
                // But find_or_insert's result isn't mutable.

                let mut value = match map.pop(&amp;key) {
                    None =&gt; { ~[] }
                    Some(old) =&gt; { old }
                };
                value.push(line);
                map.insert(key,value);
            }
        }
        return map;
    }

}
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Reader&lt;/b&gt; is an existing Rust core library trait for reading input, in this case from a file. It has a method, &lt;b&gt;each_line&lt;/b&gt;, which is an &lt;a href="http://maniagnosis.crsr.net/2013/02/rust-iterators.html"&gt;iterator&lt;/a&gt; over the lines from the input stream. What this implementation is saying is that anything that is a &lt;b&gt;Reader&lt;/b&gt; is also a &lt;b&gt;DictReader&lt;/b&gt;; any type that implements &lt;b&gt;Reader&lt;/b&gt; also implements &lt;b&gt;DictReader&lt;/b&gt;, including whatever &lt;b&gt;file_reader&lt;/b&gt; returns.&lt;/p&gt;

&lt;p&gt;How's that for spiffy?&lt;/p&gt;

&lt;p&gt;I did a similar thing for writing the output, anagram dictionary file:&lt;/p&gt;

&lt;pre&gt;
trait DictWriter {
    fn write_dict(&amp;self, dict : &amp;LinearMap&amp;lt;~str,~[~str]&gt;);
}

impl DictWriter for Writer {

    fn write_dict(&amp;self, dict : &amp;LinearMap&amp;lt;~str,~[~str]&gt;) {
        for dict.each_key_sorted() |key| {
            let line = str::connect(dict.get(key).map(|v| copy *v), " ");
            self.write_str(fmt!("%s %s\n", *key, line));
        }
    }

}
&lt;/pre&gt;

&lt;p&gt;...with a small difficulty: &lt;b&gt;LinearMap&lt;/b&gt; doesn't provide a way to iterate across the keys of the dictionary in sorted order. So, I added a third trait and implementation (see how addictive these things are?):&lt;/p&gt;

&lt;pre&gt;
trait SortedKeys&amp;lt;K : Ord&gt; {
    fn each_key_sorted(&amp;self, blk : &amp;fn(key : &amp;K) -&gt; bool);
}

impl&amp;lt;K : Hash + IterBytes + Eq + Ord, V&gt; SortedKeys&amp;lt;K&gt; for LinearMap&amp;lt;K,V&gt; {

    fn each_key_sorted(&amp;self, blk : &amp;fn(key : &amp;self/K) -&gt; bool) {
        let mut keys : ~[&amp;self/K] = vec::with_capacity(self.len());
        for self.each |&amp;(k,_)| { keys.push(k); }
        std::sort::quick_sort(keys, |a,b| *a &lt;= *b);
        for keys.each |&amp;k| { if !blk(k) { break; } }
    }

}
&lt;/pre&gt;

&lt;p&gt;...which is where the &lt;b&gt;each_key_sorted&lt;/b&gt; method in the &lt;b&gt;DictWriter&lt;/b&gt; implementation came from.&lt;/p&gt;

&lt;p&gt;The type constraints on the implementation of &lt;b&gt;SortedKeys&amp;lt;K&gt;&lt;/b&gt; for &lt;b&gt;LinearMap&amp;lt;K,V&gt;&lt;/b&gt; deserve some explanation. The &lt;b&gt;Hash&lt;/b&gt; and &lt;b&gt;Eq&lt;/b&gt; traits are required of anything that can be a key in a &lt;b&gt;LinearMap&lt;/b&gt;, and the &lt;b&gt;IterBytes&lt;/b&gt; trait is required by &lt;b&gt;Hash&lt;/b&gt; if I understand things correctly. The &lt;b&gt;Ord&lt;/b&gt; trait requirement is added by the &lt;b&gt;SortedKeys&amp;lt;K&gt;&lt;/b&gt; trait, because the keys have to be ordered in order to be sortable. That implementation declaration is saying, if a type &lt;b&gt;K&lt;/b&gt; is &lt;b&gt;Hash&lt;/b&gt;-able, &lt;b&gt;IterBytes&lt;/b&gt;-able, &lt;b&gt;Eq&lt;/b&gt;-able, &lt;i&gt;and&lt;/i&gt; &lt;b&gt;Ord&lt;/b&gt;-able, then any &lt;b&gt;LinearMap&lt;/b&gt; with keys of type &lt;b&gt;K&lt;/b&gt; also implements &lt;b&gt;Sortedkeys&lt;/b&gt; and has an &lt;b&gt;each_key_sorted&lt;/b&gt; method.&lt;/p&gt;

&lt;p&gt;The bottom line is the new implementation of mk_anadict's &lt;b&gt;main&lt;/b&gt; function:&lt;/p&gt;

&lt;pre&gt;
fn main() {
    match (file_reader(&amp;Path("/usr/share/dict/words")),
           file_writer(&amp;Path("anadict-rust.txt"), [Create,Truncate])) {
        (Ok(r),    Ok(w))     =&gt; {
            // It's like magic, but not as exciting.
            w.write_dict(r.read_dict());
        }
        (Err(msg), _)         =&gt; { fail!(msg); }
        (_,        Err(msg))  =&gt; { fail!(msg); }
    }
}
&lt;/pre&gt;

&lt;p&gt;Like magic, indeed. The neat part is that I have done &lt;i&gt;nothing&lt;/i&gt; to &lt;b&gt;file_reader&lt;/b&gt; and &lt;b&gt;file_writer&lt;/b&gt;; those functions from Rust's core &lt;b&gt;io&lt;/b&gt; module still return whatever they return; I have just added some capabilities to the values they do return.&lt;/p&gt;

&lt;p&gt;Like I wrote above, I am not advocating this style as a good way of writing idiotic programs like mk_anadict. I'm just saying that it's possible. And that you should get some exposure to traits (and type classes in Haskell) because they're powerful juju. Anyway, the trait version of the program, &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/mk_anadict_traits.rs"&gt;mk_anadict_traits.rs&lt;/a&gt;, is on github.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/3Yz2D6evd3g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/1248615839482967824/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=1248615839482967824" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1248615839482967824?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1248615839482967824?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/3Yz2D6evd3g/creating-letterpress-cheating-program_26.html" title="Creating a Letterpress cheating program in Rust: Traits" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/03/creating-letterpress-cheating-program_26.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMNRX04eSp7ImA9WhBXFE0.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-8116908372074151636</id><published>2013-03-11T11:57:00.000-05:00</published><updated>2013-03-27T11:58:14.331-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-27T11:58:14.331-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="link" /><title>Link o' the day: I've been broken by Java.</title><content type="html">From &lt;a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#getNumericValue(char)"&gt;java.lang.Character#getNumericValue(char)&lt;/a&gt;:

&lt;blockquote&gt;
&lt;pre&gt;public static int getNumericValue(char ch)&lt;/pre&gt;

&lt;p&gt;Returns the int value that the specified Unicode character represents. For example, the character '\u216C' (the roman numeral fifty) will return an int with a value of 50.&lt;/p&gt;

&lt;p&gt;The letters A-Z in their uppercase ('\u0041' through '\u005A'), lowercase ('\u0061' through '\u007A'), and full width variant ('\uFF21' through '\uFF3A' and '\uFF41' through '\uFF5A') forms have numeric values from 10 through 35. This is independent of the Unicode specification, which does not assign numeric values to these char values.&lt;/p&gt;

&lt;p&gt;If the character does not have a numeric value, then -1 is returned. If the character has a numeric value that cannot be represented as a nonnegative integer (for example, a fractional value), then -2 is returned.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; This method cannot handle supplementary characters. To support all Unicode characters, including supplementary characters, use the getNumericValue(int) method.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Parameters:&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;ch - the character to be converted.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Returns:&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;the numeric value of the character, as a nonnegative int value; -2 if the character has a numeric value that is not a nonnegative integer; -1 if the character has no numeric value.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Since:&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;1.1&lt;/p&gt;

&lt;p&gt;&lt;b&gt;See Also:&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;forDigit(int, int), isDigit(char)&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Ok, I'm with them on the first paragraph: int value of the Unicode character. But, A-Z, a-z, and their "full width" versions are 10-35? Then, -1 and -2? And it's not complete.&lt;/p&gt;

&lt;p&gt;See forDigit and isDigit? I don't think so.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;I would like to thank Del for inflicting this ghastly abomination on me. I would, really. But I can't.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/ej0NLO5DKAE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/8116908372074151636/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=8116908372074151636" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/8116908372074151636?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/8116908372074151636?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/ej0NLO5DKAE/link-o-day-ive-been-broken-by-java.html" title="Link o' the day: I've been broken by Java." /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/03/link-o-day-ive-been-broken-by-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMFQ3Yyeyp7ImA9WhBRGEQ.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-2360516605498209546</id><published>2013-03-09T11:10:00.002-06:00</published><updated>2013-03-09T23:13:32.893-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-09T23:13:32.893-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Creating a Letterpress cheating program in Rust, v2</title><content type="html">&lt;p&gt;I have updated my horrible, horrible Rust anagram-esque code for a (relatively) up-to-date build of the Rust *master* branch, rustc 0.6 (edcebac 2013-03-03 20:02:06 -0800). There were a number of simple syntax changes, along with a much nicer hashmap.&lt;/p&gt;

&lt;p&gt;I also fixed a grotesque performance problem that improved the Rust programs' times considerably, so these times are not *directly* comparable to &lt;a href="http://maniagnosis.crsr.net/2013/02/creating-letterpress-cheating-program.html"&gt;the previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To start, here are the current timings:&lt;/p&gt;

&lt;table style="margin-left:auto; margin-right:auto;"&gt;
&lt;tr&gt;&lt;th style="text-align:center"&gt;Program&lt;/th&gt;&lt;th style="text-align:center"&gt;Duration (sec)&lt;/th&gt;&lt;th style="text-align:center"&gt;Speedup&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/presser_one.py"&gt;pesser_one.py&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;49.7&lt;/td&gt;&lt;td style="text-align:right"&gt;1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/presser_two.py"&gt;presser_two.py&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;12.5&lt;/td&gt;&lt;td style="text-align:right"&gt;4&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors.rs"&gt;anagrams-vectors.rs&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;7.9&lt;/td&gt;&lt;td style="text-align:right"&gt;6&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/presser_three.py"&gt;presser_three.py&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;6.0&lt;/td&gt;&lt;td style="text-align:right"&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-hashmap.rs"&gt;anagrams-hashmap.rs&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;5.8&lt;/td&gt;&lt;td style="text-align:right"&gt;9&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/anagrams-vectors.c"&gt;anagrams-vectors.c&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;5.6&lt;/td&gt;&lt;td style="text-align:right"&gt;9&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/anagrams-hash.c"&gt;anagrams-hash.c&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;0.9&lt;/td&gt;&lt;td style="text-align:right"&gt;55&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Once again, the argument for all of these runs was "asdwtribnowplfglewhqagnbe", which produces 7440 results from my dictionary; I get 33,554,406 combinations to look at. I used Python 2.7.3; gcc 4.6.3, with -O3; and rustc, with -O.&lt;/p&gt;

&lt;p&gt;So, what did I change?&lt;/p&gt;

&lt;p&gt;Overall, I'm now using core::hashmap::linear::LinearMap and LinearSet instead of the HashMap that used to be in the std crate. LinearMap has a much nicer, if still imperfect, interface.&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;fail&lt;/b&gt; "keyword" is now a macro: &lt;b&gt;fail!&lt;/b&gt;.&lt;/p&gt;

&lt;h2&gt;anagrams-vectors.rs&lt;/h2&gt;

&lt;p&gt;The previous version use a (owned) vector of (owned) vectors of chars to store the "keys" from the dictionary file: ~[~[char]]. To look up a key, made from a combination of the input letters (a (borrowed) vector of chars), I use a binary search into this vector. To make the binary search work, two vectors of chars need to be comparable, to implement the Ord trait. Unfortunately (and I need to check on this), char's don't have an implementation of Ord. So, I added one:&lt;/p&gt;

&lt;pre&gt;
impl char : Ord {
    #[inline(always)] pure fn lt(&amp;self, other: &amp;char) -&gt; bool { *self &amp;lt;  *other }
    #[inline(always)] pure fn le(&amp;self, other: &amp;char) -&gt; bool { *self &amp;lt;= *other }
    #[inline(always)] pure fn gt(&amp;self, other: &amp;char) -&gt; bool { *self &amp;gt;  *other }
    #[inline(always)] pure fn ge(&amp;self, other: &amp;char) -&gt; bool { *self &amp;gt;= *other }
}
&lt;/pre&gt;

&lt;p&gt;One of the recent changes to rustc, however, makes that illegal because &lt;a href="http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/"&gt;it is problematic to implement a trait for a type originating from a different crate&lt;/a&gt;. As a result, I removed that implementation and made the keys vectors of int's (converting the char's to int's). The int's &lt;i&gt;are&lt;/i&gt; comparable.&lt;/p&gt;

&lt;p&gt;By the way, one of the syntax changes was to replace "impl char : Ord ..." with "impl Ord for char...". That declaration is now much more readable.&lt;/p&gt;

&lt;h2&gt;anagrams-hashmap.rs&lt;/h2&gt;

&lt;p&gt;Once again, I converted the vector of char's to a vector of int's. In this case, that did not result in any major changes.&lt;/p&gt;

&lt;p&gt;The major performance change (which I did make to both programs) was to move the allocation of the actual key used by the lookup out of the each_combination inner loop. &lt;i&gt;That&lt;/i&gt; is the major performance change.&lt;/p&gt;

&lt;p&gt;The combination provided by each_combination is a &amp;[int], while the call to dictionary.find(...) wants a &amp;~[int] because the key type, K, for the dictionary is ~[int]. As a result, I need to copy the combination's values out of one vector and into an appropriately allocated vector. The previous version was allocating the copy in the inner loop; this version allocates it in the outer loop, where the size is known, and inserts the values in the inner loop. In other words, the previous version had:&lt;/p&gt;

&lt;pre&gt;
let key = @vec::from_fn(combo.len(), |i| combo[i]);
&lt;/pre&gt;

&lt;p&gt;(You can ignore the "@", which was needed by the previous hashmap to make the key's Copy-able.)&lt;/p&gt;

&lt;p&gt;The current version uses:&lt;/p&gt;

&lt;pre&gt;
let mut key = vec::from_elem(size, 0);              // outer loop
...
    for uint::range(0,i) |j| { key[j] = combo[j]; } // inner loop
&lt;/pre&gt;

&lt;p&gt;Avoiding the allocation was a big win. Avoiding the copy would also be a win, but I don't know how to do that. Yet.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/SDxR37t3g38" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/2360516605498209546/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=2360516605498209546" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2360516605498209546?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2360516605498209546?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/SDxR37t3g38/creating-letterpress-cheating-program.html" title="Creating a Letterpress cheating program in Rust, v2" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/03/creating-letterpress-cheating-program.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ECQXw-eip7ImA9WhBRF0U.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-4777596992536665153</id><published>2013-03-08T18:41:00.000-06:00</published><updated>2013-03-08T18:41:00.252-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-08T18:41:00.252-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="link" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><title>Link o' the day: The Deep Insights of Alan Kay</title><content type="html">&lt;p&gt;At a meeting I recently attended, a coworker asked, "Is &lt;i&gt;anyone&lt;/i&gt; going past low earth orbit in the next 50 years?"&lt;/p&gt;

&lt;p&gt;"Well, lots of states are making marijuana legal," I replied&lt;/p&gt;

&lt;p&gt;&lt;a href="http://mythz.servicestack.net/blog/2013/02/27/the-deep-insights-of-alan-kay/"&gt;Alan Kay&lt;/a&gt; is my nomination for the computer science equivalent of astronautical marijuana.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/DeIVxsL7f-8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/4777596992536665153/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=4777596992536665153" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/4777596992536665153?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/4777596992536665153?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/DeIVxsL7f-8/link-o-day-deep-insights-of-alan-kay.html" title="Link o' the day: The Deep Insights of Alan Kay" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/03/link-o-day-deep-insights-of-alan-kay.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMEQXw7fip7ImA9WhBRF0w.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-932927177247870585</id><published>2013-03-07T21:28:00.000-06:00</published><updated>2013-03-07T21:30:00.206-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-07T21:30:00.206-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="link" /><category scheme="http://www.blogger.com/atom/ns#" term="unix" /><title>Link(s) o' the day: Unix CLI tricks</title><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mmb.pcb.ub.es/~carlesfe/unix/tricks.txt"&gt;Unix tricks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Commandlinefu: &lt;a href="http://www.commandlinefu.com/commands/browse/sort-by-votes"&gt;all commands sorted by votes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href="http://en.wikipedia.org/wiki/Magic_SysRq_key"&gt;Magic SysRq key&lt;/a&gt;.
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/dmskUG_9GBA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/932927177247870585/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=932927177247870585" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/932927177247870585?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/932927177247870585?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/dmskUG_9GBA/links-o-day-unix-cli-tricks.html" title="Link(s) o' the day: Unix CLI tricks" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/03/links-o-day-unix-cli-tricks.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MBRXs_eyp7ImA9WhBRFkU.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-1149349423208012589</id><published>2013-03-07T14:50:00.002-06:00</published><updated>2013-03-07T14:50:54.543-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-07T14:50:54.543-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quote" /><category scheme="http://www.blogger.com/atom/ns#" term="protocols" /><title>Quote o' the day: A bell you can't un-ring</title><content type="html">&lt;p&gt;From &lt;a href="http://www.punk.co.nz/2013/03/07/crafting-a-basic-ethernet-mac-and-10base-t-phy/"&gt;Crafting a basic Ethernet MAC and 10BASE-T PHY&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;So without further ado it’s time to cut the end off a CAT5 cable and start jamming wires into I/O ports.&lt;/blockquote&gt;

&lt;p&gt;In my experience, that doesn't usually end well.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/Y1lwzHgk5qk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/1149349423208012589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=1149349423208012589" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1149349423208012589?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1149349423208012589?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/Y1lwzHgk5qk/quote-o-day-bell-you-cant-un-ring.html" title="Quote o' the day: A bell you can't un-ring" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/03/quote-o-day-bell-you-cant-un-ring.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YBRn86fip7ImA9WhBRGEk.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-2189192936495957382</id><published>2013-02-25T22:31:00.000-06:00</published><updated>2013-03-09T11:12:37.116-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-09T11:12:37.116-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="c" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Creating a Letterpress cheating program in Rust</title><content type="html">&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; &lt;a href="http://maniagnosis.crsr.net/2013/03/creating-letterpress-cheating-program.html"&gt;Creating a Letterpress cheating program in Rust, v2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I believe I have mentioned, I have been casually learning &lt;a href="http://www.rust-lang.org/"&gt;Rust&lt;/a&gt; (currently, Rust 0.5) by working on a port of Jeff Knupp's &lt;a href="http://www.jeffknupp.com/blog/2013/01/04/creating-and-optimizing-a-letterpress-cheating-program-in-python/"&gt;Creating and Optimizing a Letterpress Cheating Program in Python&lt;/a&gt;. It's now time to describe my current progress.&lt;/p&gt;

&lt;p&gt;For those of you with short attention spans, this is the punchline:&lt;/p&gt;

&lt;table style="margin-left:auto; margin-right:auto;"&gt;
&lt;tr&gt;&lt;th style="text-align:center"&gt;Program&lt;/th&gt;&lt;th style="text-align:center"&gt;Duration (sec)&lt;/th&gt;&lt;th style="text-align:center"&gt;Speedup&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/presser_one.py"&gt;pesser_one.py&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;49.7&lt;/td&gt;&lt;td style="text-align:right"&gt;1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-hashmap.rs"&gt;anagrams-hashmap.rs&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;24.0&lt;/td&gt;&lt;td style="text-align:right"&gt;2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/anagrams-vectors.rs"&gt;anagrams-vectors.rs&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;17.6&lt;/td&gt;&lt;td style="text-align:right"&gt;3&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/presser_two.py"&gt;presser_two.py&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;12.5&lt;/td&gt;&lt;td style="text-align:right"&gt;4&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/presser_three.py"&gt;presser_three.py&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;6.0&lt;/td&gt;&lt;td style="text-align:right"&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/anagrams-vectors.c"&gt;anagrams-vectors.c&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;5.6&lt;/td&gt;&lt;td style="text-align:right"&gt;9&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/alternatives/anagrams-hash.c"&gt;anagrams-hash.c&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:right"&gt;0.9&lt;/td&gt;&lt;td style="text-align:right"&gt;55&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The argument for all of these runs was "asdwtribnowplfglewhqagnbe", which produces 7440 results from my dictionary; I get 33,554,406 combinations. I used Python 2.7.3; gcc 4.6.3, with -O3; and rustc 0.5, with -O. (I missed "--opt-level 3" the first time around and did get some improvement when I used it. But that's not shown here.)&lt;/p&gt;

&lt;p&gt;I started by getting all three of the Python versions from Knupp working, to have something to compare against. (I would like to point out that presser_one.py is not something I would consider idiomatic Python, but I do need something to make the rest look better.) Then, I wrote the anagrams-hashmap Rust version, the meat of which looks like:&lt;/p&gt;

&lt;pre&gt;
fn main() {
    let args = os::args();
    if args.len() &amp;lt; 2 { fail ~"Usage: anagrams letters"; }
    let mut letters = str::chars(args[1]);
    std::sort::quick_sort(letters, |a,b| *a &amp;lt;= *b);
    let dictionary = load_dictionary();
    let mut set : Set&amp;lt@~str&gt; = HashMap();
    for uint::range(2,letters.len()) |i| {
        for combinations::each_combination_ref(letters,i) |combo| {
            let ana = @vec::from_fn(combo.len(), |i| *combo[i]);
            match dictionary.find(ana) {
                Some(ref val) =&gt; {
                    for val.each() |word| { set_add(set, *word); }
                }
                None =&gt; { }
            }
        }
    }
    let result = vec_from_set(set);
    println(fmt!("%u", result.len()));
}
&lt;/pre&gt;

&lt;p&gt;This code uses the each_combination function I described last time. Unfortunately, the hashmap interface (and implementation) are a bit of a mess in 0.5, leading to some unpleasant code and probably poor performance. Specifically, I'm looking at the line "@vec::from_fn(combo.len(), |i| *combo[i])", which copies the contents of the combination vector into a separate vector, since the call to "find(ana)" is going to take ownership.&lt;/p&gt;

&lt;p&gt;Unhappy with the performance of that, I wrote the anagrams-vectors Rust version, which avoids the use of the hashmap for the dictionary, replacing it with a binary search similar to presser_one.py. In fact, it uses a conversion of the same &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/bisect.rs"&gt;bisect_left&lt;/a&gt; function. The fact that anagrams-vectors shows improvement should tell you there's something fishy in the state of Denmark (er, hashmap). (Unfortunately, the Set used to contain the resulting words is a thin wrapper on the hashmap, so I did not completely remove that module.)&lt;/p&gt;

&lt;p&gt;Following several attempts to improve the Rust results without much success, I decided to dust off my C and go old-school, medieval in fact, on this sucker. I first came up with the vector-based C version, which mmaps the anagram dictionary file and builds its dictionary structure based on that file's sorted lines. Given that attempt's not-completely-satisfactory success, I added the hash version, which builds a pseudo-hashtable over the mmap'ed dictionary. That version is about as far as I'm willing to go at the moment.&lt;/p&gt;

&lt;p&gt;There are probably a few worthwhile notes on the C versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no reusability in the C code. I'm not sure if there would be a point, given the focus on getting the fastest code quickly. On the other hand, it is fairly difficult to build reusable data structures such as hashmaps in C.&lt;/li&gt;
&lt;li&gt;I am using some less-well-known parts of C. mmap is one example; another is using alloca for memory allocation; it puts the allocated space in the current stack frame, making deletion easier. (On the other hand, you can blow your stack pretty easily with it.)&lt;/li&gt;
&lt;li&gt;The hash is djb2 from &lt;a href="http://www.cse.yorku.ca/~oz/hash.html"&gt;Hash Functions&lt;/a&gt;; it is dead simple and works fairly well. To keep the maximum chain length down (for linear chaining), the hashtable load factor is a pitiful 0.2; I tried several other values, but increasing it did cost time, while decreasing it further did not offer much improvement. For a load factor of 0.5, the maximum chain length was 41 if I remember correctly, for 0.2, it was 9 with 58505 entries.&lt;/li&gt;
&lt;li&gt;I used a bitset to hold the results, noting that each word in the output could come from exactly one line, all of the words on the line would appear if any did, and each line could appear exactly once. Yes, that's 58,000 bits. Using integers did not seem to make any special difference over the bit-manipulations, and I &lt;i&gt;was&lt;/i&gt; worried about stack space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I expect the performance to improve as Rust work continues. In fact, the hashmap interface is much better in the version in the core library in &lt;i&gt;incoming&lt;/i&gt;. When 0.6 lands (or sooner), I'll update this code and provide up-to-date results.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/vDYKqKivPsE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/2189192936495957382/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=2189192936495957382" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2189192936495957382?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2189192936495957382?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/vDYKqKivPsE/creating-letterpress-cheating-program.html" title="Creating a Letterpress cheating program in Rust" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/02/creating-letterpress-cheating-program.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YASH07eCp7ImA9WhBWEUU.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-9089228734349197422</id><published>2013-02-21T20:42:00.000-06:00</published><updated>2013-04-05T14:12:29.300-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-05T14:12:29.300-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="notation" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Rust Iterators</title><content type="html">&lt;p&gt;In my &lt;a href="http://maniagnosis.crsr.net/2013/02/exploring-rust.html"&gt;last post&lt;/a&gt;, I described my first &lt;a href="http://www.rust-lang.org/"&gt;Rust&lt;/a&gt; program, a simple utility to build an anagram dictionary based on part of Jeff Knupp's &lt;a href="http://www.jeffknupp.com/blog/2013/01/04/creating-and-optimizing-a-letterpress-cheating-program-in-python/"&gt;Python Letterpress cheating program&lt;/a&gt;. This time, I would like to take a closer look at a slightly unusual part of Rust by presenting an implementation of part of Python's &lt;a href="http://docs.python.org/2/library/itertools.html"&gt;itertools&lt;/a&gt; module that is needed by the remainder of the anagram-esqe program.&lt;/p&gt;

&lt;p&gt;In order to find all the words that can be built from a set of characters, Jeff uses &lt;a href="http://docs.python.org/2/library/itertools.html#itertools.combinations"&gt;combinations&lt;/a&gt;, a function which "[returns] &lt;i&gt;r&lt;/i&gt; length subsequences of elements from the input &lt;i&gt;iterable&lt;/i&gt;. Combinations are emitted in lexicographic sort order. So, if the input &lt;i&gt;iterable&lt;/i&gt; is sorted, the combination tuples will be produced in sorted order." According to the documentation, &lt;code&gt;combinations('ABCD', 2)&lt;/code&gt; produces "AB", "AC", "AD", "BC", "BD", "CD". The Rust standard library doesn't include anything like this function.&lt;/p&gt;

&lt;p&gt;What Rust does have is a style of iterators based on higher-order functions. For example, to iterate across all the elements of a vector, the function &lt;code&gt;vec::each&lt;/code&gt; takes a vector and a function to be applied to each element: &lt;code&gt;each(v, |elt| { frob(elt) })&lt;/code&gt; (or alternatively, the "method" version is an element of a typeclass with an implementation for vectors, allowing it to be called as &lt;code&gt;v.each(|elt| { frob(elt) })&lt;/code&gt;). Now, the way this function works is that the function argument should return true or false after processing each element; if it returns false, the iteration terminates. In other words, the frob function should return a boolean in those examples.&lt;/p&gt;

&lt;p&gt;Rust provides a couple of special syntactic forms that make these higher-order functions easier to use: &lt;a href="http://static.rust-lang.org/doc/0.5/rust.html#do-expressions"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/a&gt; and &lt;a href="http://static.rust-lang.org/doc/0.5/rust.html#for-expressions"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/a&gt; expressions. The syntax for the &lt;b&gt;for&lt;/b&gt; expression is:&lt;/p&gt;
&lt;blockquote&gt;
"for" expr [ '|' ident_list '|' ] ? '{' block '}' ;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;b&gt;do&lt;/b&gt; expression differs only in the keyword. &lt;b&gt;do&lt;/b&gt; is the simpler of the two; to illustrate, the Rust manual describes the following two expressions as identical:&lt;/p&gt;
&lt;pre&gt;
f(|j| g(j));

do f |j| {
    g(j);
}
&lt;/pre&gt;
&lt;p&gt;The higher-order function is &lt;i&gt;f&lt;/i&gt;, &lt;i&gt;j&lt;/i&gt; is the parameter to the anonymous function, which in turn calls &lt;i&gt;g&lt;/i&gt; with &lt;i&gt;j&lt;/i&gt;. One feature of this syntactic form is that a &lt;b&gt;return&lt;/b&gt; expression in the body of the anonymous function returns from the function enclosing the &lt;b&gt;do&lt;/b&gt; expression, not the inner anonymous function. Likewise, &lt;b&gt;break&lt;/b&gt; and &lt;b&gt;loop&lt;/b&gt; are handled specially, allowing the expression to behave more like a control structure. (The latter is similar to &lt;b&gt;continue&lt;/b&gt; in many other languages, in this use.)&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;for&lt;/b&gt; expression is similar, but more specialized. In addition to the specialized handling of &lt;b&gt;return&lt;/b&gt;, the anonymous function forming the body of the &lt;b&gt;for&lt;/b&gt; expression implicitly returns &lt;b&gt;true&lt;/b&gt;, continuing the iteration. The Rust tutorial provides this example:&lt;/p&gt;
&lt;pre&gt;
for each([2, 4, 8, 5, 16]) |n| {
    if *n % 2 != 0 {
        println("found odd number!");
        break;
    }
}
&lt;/pre&gt;
&lt;p&gt;The signature of each is &lt;code&gt;fn each&lt;'r,T&gt;(v: &amp;'r [T], f: &amp;fn(&amp;'r T) -&gt; bool)&lt;/code&gt;; &lt;i&gt;v&lt;/i&gt; is the vector argument and &lt;i&gt;f&lt;/i&gt; is the function. (For the moment, ignore the "&amp;'r" bit.)&lt;/p&gt;

&lt;p&gt;How does this interact with combinations? How about an each-like function that takes arguments describing what and how many to combine, and a function to apply to each combination as it is generated? Without too much introduction, this is what I came up with:&lt;/p&gt;

&lt;pre&gt;
pub pure fn each_combination&amp;lt;T:Copy&gt;(values : &amp;[T],
                                     r : uint,
                                     fun : &amp;fn(combo : &amp;[T]) -&gt; bool) {
    let length = values.len();
    if r == 0 || r &gt; length { return; }
    let max_indices0 = length - r;
    let mut indices = vec::from_fn(r, |i| i);
    let mut combination = vec::from_fn(r, |i| values[i]);
    loop {
        if !fun(combination) { return; }
        let mut i = r - 1;
        indices[i] += 1;
        while i &gt; 0 &amp;&amp; indices[i] &gt; max_indices0 + i {
            i -= 1;
            indices[i] += 1;
        }
        if indices[0] &gt; max_indices0 { break; }
        combination[i] = values[indices[i]];
        for uint::range(i + 1, r) |i| {
            indices[i] = indices[i-1] + 1;
            combination[i] = values[indices[i]];
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;This function first tests whether any iterations are needed, then creates a pair of vectors to handle those needed. &lt;i&gt;indices&lt;/i&gt; is a vector of integers, the size of the combinations that are needed, containing the indices into the &lt;i&gt;values&lt;/i&gt; argument for the current combination. The &lt;i&gt;combination&lt;/i&gt; vector contains the &lt;i&gt;r&lt;/i&gt; elements from &lt;i&gt;values&lt;/i&gt; (specifically, copies of them) for the current combination. Specifially, the loop tries to maintain combination[i] = values[indices[i], for i in 0 to &lt;i&gt;r-1&lt;/i&gt;. The contents of the &lt;i&gt;indices&lt;/i&gt; vector are incremented lexicographically, with the first, &lt;b&gt;while&lt;/b&gt;, inner loop locating the right-most index to be incremented and the second, &lt;b&gt;for&lt;/b&gt; loop, fixing up the subsequent indices as well as the &lt;i&gt;combination&lt;/i&gt; vector. The overall loop terminates when the left-most index, &lt;i&gt;indices[0]&lt;/i&gt; is too large to allow the remainder of &lt;i&gt;indices&lt;/i&gt; to fit into &lt;i&gt;values&lt;/i&gt;. Or when &lt;i&gt;fun&lt;/i&gt; returns false after being invoked with a combination.&lt;/p&gt;

&lt;p&gt;There are a couple of minor points to notice about this function. First, it is marked &lt;b&gt;pure&lt;/b&gt;, indicating that it only modifies data &lt;i&gt;owned by its own stack frame&lt;/i&gt;; meaning that aside from internal manipulations, it is (ideally) referentially transparent. Second, notice that &lt;i&gt;indices&lt;/i&gt;, &lt;i&gt;combination&lt;/i&gt;, and the helper &lt;i&gt;i&lt;/i&gt; are declared &lt;b&gt;mut&lt;/b&gt;, meaning that these variables are mutable; otherwise variables in Rust are immutable.&lt;/p&gt;

&lt;p&gt;Third, the type parameter of &lt;i&gt;each_combination&lt;/i&gt;, &lt;i&gt;T&lt;/i&gt;. Because elements from &lt;i&gt;values&lt;/i&gt; are copied into &lt;i&gt;combination&lt;/i&gt;, &lt;i&gt;T&lt;/i&gt; must be copyable, indicated by the Copy typeclass. Requiring that, in general, seems sub-optimal, so I created a second, much shorter, function that uses &lt;i&gt;each_combination&lt;/i&gt; but does not require &lt;i&gt;T&lt;/i&gt; to be copyable.&lt;/p&gt;

&lt;pre&gt;
pub pure fn each_combination_ref&amp;lt;'v,T&gt;(values : &amp;'v [T],
                                    r : uint,
                                    fun : &amp;fn(combo : &amp;[&amp;'v T]) -&gt; bool) {
    each_combination(vec::from_fn(values.len(), |i| &amp;values[i]), r, fun);
}
&lt;/pre&gt;

&lt;p&gt;This function creates a vector containing borrowed pointers to the elements of the original &lt;i&gt;values&lt;/i&gt;, then calls &lt;i&gt;each_combination&lt;/i&gt; on it. Since the borrowed pointers are being copied, not the contents of the vector, &lt;i&gt;T&lt;/i&gt; no longer needs to be copyable and as a side effect (if &lt;i&gt;T&lt;/i&gt; is large enough, say) this function may be more efficient. The function parameter must be different, of course, in that it acts on a borrowed pointer to a vector containing borrowed pointers to the value elements. That is where Rust's type system gets interesting.&lt;/p&gt;

&lt;p&gt;Check out the type of &lt;i&gt;values&lt;/i&gt; and the type of &lt;i&gt;combo&lt;/i&gt;, the parameter to the function &lt;i&gt;fun&lt;/i&gt;. The type of &lt;i&gt;values&lt;/i&gt; is &lt;code&gt;&amp;'v [T]&lt;/code&gt;, indicating that it is a borrowed pointer to a vector containing &lt;i&gt;T&lt;/i&gt;'s, with a &lt;b&gt;lifetime variable&lt;/b&gt; of &lt;i&gt;v&lt;/i&gt;. The type of &lt;i&gt;combo&lt;/i&gt; is &lt;code&gt;&amp;[&amp;'v T]&lt;/code&gt;, which is a borrowed pointer to a vector containing borrowed pointers to &lt;i&gt;T&lt;/i&gt;'s, here the inner borrowed pointers have the same lifetime variable, &lt;i&gt;v&lt;/i&gt;. [Note: the syntax for lifetime variables will be changing in Rust 0.6.]&lt;/p&gt;

&lt;p&gt;Those types are telling the Rust compiler that the contents of &lt;i&gt;combo&lt;/i&gt; can be used anywhere that doesn't live any longer than &lt;i&gt;values&lt;/i&gt;. Equivalent C code could easily leak the pointers into &lt;i&gt;values&lt;/i&gt;, leaving them dangling if that vector were freed.&lt;/p&gt;

&lt;p&gt;Niko Matsakis described the &lt;b&gt;for&lt;/b&gt; loop protocol in detail, along with a significant problem and proposed solution: &lt;a href="http://smallcultfollowing.com/babysteps/blog/2013/01/16/revised-for-loop-protocol/"&gt;Revised for loop protocol&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update 4/5/2013:&lt;/b&gt; Updated to use rust 0.6 lifetime syntax. "&amp;v/T" became "&amp;'v T". Also, the library modules have the lifetime, "'v", as the first of the type parameters as shown above, although that is not mentioned in the manual or RELEASES.txt.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/mTYK6jqj-Pw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/9089228734349197422/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=9089228734349197422" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/9089228734349197422?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/9089228734349197422?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/mTYK6jqj-Pw/rust-iterators.html" title="Rust Iterators" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/02/rust-iterators.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMBQH07eSp7ImA9WhBSEEU.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-3608459127928125592</id><published>2013-02-17T00:24:00.000-06:00</published><updated>2013-02-17T00:27:31.301-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-17T00:27:31.301-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><category scheme="http://www.blogger.com/atom/ns#" term="rust" /><title>Exploring Rust</title><content type="html">&lt;p&gt;Of the current crop of new programming languages, the one that I've been most interested in is &lt;a href="http://www.rust-lang.org/"&gt;Rust&lt;/a&gt;, a "safe, concurrent, practical language" that is intended for "&lt;a href="http://www.infoq.com/news/2012/08/Interview-Rust"&gt;frustrated C++ developers&lt;/a&gt;", with features intended to improve "systems" programming currently done in C and C++. Those features are mostly things that have been floating around the programming language community for decades, but have not been applied to a low-level language that also addresses issues like memory layout and garbage-collection avoidance.&lt;/p&gt;

&lt;p&gt;The only way to learn a programming language is to write programs using it. Unfortunately, I have only limited natural creativity, so I need a little help in finding programs to write. In this case, the inspiration was &lt;a href="http://www.jeffknupp.com/blog/2013/01/04/creating-and-optimizing-a-letterpress-cheating-program-in-python/"&gt;Creating and Optimizing a Letterpress Cheating Program in Python&lt;/a&gt;, in which Jeff Knupp presents some Python to find all of the words which can be made from a set of letters. (No, it's not really anagrams, but it's close. Yes, I know my naming sucks.)&lt;/p&gt;

&lt;p&gt;The first step in the program, and my first step in Rust, is a program to convert the Unix words file into an anagram dictionary. This is my version in Rust; I would greatly appreciate any comments or suggestions. I am currently using Rust 0.5, which is an important point; Rust is changing rapidly. Also, I am not making any claim that this is a particularly good Rust program.&lt;/p&gt;

&lt;pre&gt;
fn main() {
    match (file_reader(&amp;Path("/usr/share/dict/words")),
           file_writer(&amp;Path("anadict-rust.txt"), [Create,Truncate])) {
        (Ok(r),    Ok(w))    =&gt; { print_dict(w, read_dict(r)); }
        (Err(msg), _)        =&gt; { fail msg; }
        (_,        Err(msg)) =&gt; { fail msg; }
    }
}
&lt;/pre&gt;

&lt;p&gt;Beginning at the end, the main function opens a reader on the words file and a writer on a dictionary file. Both of those operations can fail, so the return type for file_reader, for example, is Result&amp;lt;Reader, ~str&amp;gt;; a Reader object implements the interface to read the file while the str represents the error message. In fact, the error message is a ~str, an &lt;i&gt;owned&lt;/i&gt; pointer to a dynamically allocated string; a string allocated on the "owned" heap which will be deleted when the (single) owning reference to it goes away. The two variants of the Result are the constructors Ok and Err. (If you are familiar with Haskell or any of the ML languages, Result is a specialization of an Either algebraic data type.)&lt;/p&gt;

&lt;p&gt;This function first creates a pair of Results, then uses pattern matching to deconstruct the two results. If both are Ok, the program reads the words file, building a dictionary, and then writes the dictionary out. Otherwise, it fails with an error message. The patterns are tried in order, so if both fail then only the reader message will be produced.&lt;/p&gt;

&lt;p&gt;The read_dict function produces a HashMap (on the owned heap) mapping strings to vectors of strings. The value is a list of words made from the same set of letters while the key is the sorted letters. There are some peculiarities here; let me go over the relatively normal processing before getting into them.&lt;/p&gt;

&lt;pre&gt;
fn read_dict(reader : Reader) -&gt; ~HashMap&amp;lt;@~str,@[@~str]&gt; {
    let map = ~HashMap();                             &lt;b&gt;// [1]&lt;/b&gt;
    for reader.each_line |line| {                     &lt;b&gt;// [2]&lt;/b&gt;
        let line   = line.trim();
        let length = line.len();
        // Original is using pre-strip() line for comparisons
        if length &gt;= 2 &amp;&amp; length &amp;lt; 19 &amp;&amp; line.all(|ch| (char::is_ascii(ch) &amp;&amp; char::is_lowercase(ch))) {
            let mut chars = str::chars(line);         &lt;b&gt;// [3]&lt;/b&gt;
            std::sort::quick_sort(chars, |a,b| *a &amp;lt;= *b);
            let key = str::from_chars(chars);
            map.update(@key, @[@line], |old,nw| at_vec::append(old,nw));
        }
    }
    return map;
}
&lt;/pre&gt;

&lt;p&gt;The line marked [1] allocates the Hashmap on the owned heap. The type is inferred, based on the keys and values and the function return type.&lt;/p&gt;

&lt;p&gt;The line [2] is a use of Rust's iterator pattern. The function each_line, used as a method on the reader, takes one argument, a function to which is passed the line just read. This function is supposed to return true or false, indicating whether or not the iteration is to continue. However, special syntax and semantics are provided by the for keyword; since each_line has no other arguments, the parentheses are optional, and the function is provided by an anonymous function immediately following each_line. "|line|" is the parameter list for the anonymous function, while the body follows in braces. Another feature of the for keyword is that the anonymous function automatically returns true.&lt;/p&gt;

&lt;p&gt;The major processing of the anonymous function filters out words of less than one character or more than 18, or which are made up of non-lowercase ASCII. The key for the HashMap is made by breaking the words into a vector of characters, then sorting and re-forming a string. The value is a vector containing the word, if the map does not already have a matching key, or the combination of the existing list and the new word if it does.&lt;/p&gt;

&lt;p&gt;The second argument to the quick_sort function, "|a,b| *a &amp;lt;= *b", is another anonymous function, used to compare characters while sorting. The "mut" keyword on line [3], by the way, marks the chars vector as mutable, allowing it to be sorted.&lt;/p&gt;

&lt;p&gt;A tilde indicates a pointer to the owned heap, but an at-sign, @, indicates a pointer into the managed heap. Rust's managed heap is a garbage-collected area local to the one thread. With the current library, most functions such as str::chars and str::from_chars produce owned pointers, a vector of characters and a string, respectively. Also, the HashMap requires its keys and values to be copyable, which owned strings in particular are not. To avoid warnings and excess copying, I am using @~str, a managed pointer to an owned string.&lt;/p&gt;

&lt;p&gt;Fortunately, writing the dictionary is simpler. Since it is important that the resulting file is in sorted order, print_dict first gets the sorted keys to the dictionary. For each one, it gets the values, joins them into a string separated by spaces, and writes the formatted line out.&lt;/p&gt;

&lt;pre&gt;
fn print_dict(writer : Writer, dict : &amp;HashMap&amp;lt;@~str,@[@~str]&gt;) {
    for sorted_keys(dict).each |key| {
        let line = str::connect( dict.get(*key).map(|v| **v), " " );
        writer.write_str( fmt!("%s %s\n", **key, line) );
    }
}
&lt;/pre&gt;

&lt;p&gt;The * operator in this code dereferences a pointer; the key in the anonymous function is a borrowed (the third type) pointer, pointing to the @~str HashMap key. As a result, "*key" (the argument to the map function, is a @~str, while the value of the anonymous method "|v| **v" is a ~str, a vector of which is the correct argument to str::connect.&lt;/p&gt;

&lt;p&gt;Naturally, sorted_keys is not a function from the library.&lt;/p&gt;

&lt;pre&gt;
fn sorted_keys&amp;lt;V:Copy&gt;(dict : &amp;HashMap&amp;lt;@~str,V&gt;) -&gt; ~[@~str] {
    let mut keys = vec::with_capacity( dict.size() );
    for dict.each_key |key| { keys.push(key); }
    std::sort::quick_sort(keys, |a,b| *a &amp;lt;= *b);
    return keys;
}
&lt;/pre&gt;

&lt;p&gt;"&amp;lt;V:Copy&gt;" is a type parameter to sorted_keys; V is the type variable, which must satisfy the Copy typeclass, which is in turn needed by the HashMap. This type signature simply indicates that this function does not care about the type of values of the map.&lt;/p&gt;

&lt;p&gt;Pattern matching, algebraic data types, anonymous and higher-order functions, type inference, parametric polymorphism, type classes, a confusing variety of memory allocation strategies, a somewhat chaotic library.... Rust is &lt;i&gt;entertaining&lt;/i&gt;, at least.&lt;/p&gt;

&lt;p&gt;The code is available on &lt;a href="https://github.com/tmmcguire/rust-toys/blob/master/mk_anadict.rs"&gt;Github&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/fvmqm8qGFuU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/3608459127928125592/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=3608459127928125592" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/3608459127928125592?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/3608459127928125592?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/fvmqm8qGFuU/exploring-rust.html" title="Exploring Rust" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/02/exploring-rust.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4GQXs4fCp7ImA9WhNaFUQ.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-4138067610992041487</id><published>2013-01-30T20:22:00.000-06:00</published><updated>2013-01-30T20:22:00.534-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T20:22:00.534-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="lisp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><title>Brian Harvey on Scheme vs. Python</title><content type="html">&lt;p&gt;&lt;a href="http://www.cs.berkeley.edu/~bh/proglang.html"&gt;Scheme vs. Python&lt;/a&gt; is an excellent read, but I would be more impressed if he took points 3 and 4 out back and shot them in the head. "[Y]ou should be able to learn a programming language (after the first time) over a weekend" is perfectly true (for some reasonable value of "weekend"), for a Computer Science program. "The best language for a course is not necessarily the best language for writing real-world code" is an excellent point as well. "You can learn to program in any language [but] the big ideas in [SICP]...express themselves best in Scheme" is (arguably, I admit) also valid.&lt;/p&gt;

&lt;p&gt;But points 3 and 4 are, first of all, the same "Everyone should use Lisp" argument that hasn't actually convinced anyone in the 50-year history of Lisp. They weaken the actual point I think he's trying to make, or at least that I wish he was trying to make.&lt;/p&gt;

&lt;p&gt;What, exactly does "the lifespan of a programming language is closer to the lifespan of a dog than to that of a person" mean? What is the lifespan of a programming language? I don't know of any programming languages that have achieved some kind of critical mass that can be meaningfully said to have "died".&lt;/p&gt;

&lt;p&gt;Furthermore, fundamentally, what is "Lisp"? LISP 1.5, a la McCarthy? Is anyone still using that? Common Lisp? Good luck with recursion there; recursion without tail call elimination is not an especially good idea. Scheme != Lisp, any more than C, C++, Java, et al., are the same as ALGOL. There are ideas that unite all of these languages, but the fundamental one, that programs &lt;i&gt;are&lt;/i&gt; data and that data is a program, is not one of "Lisp’s ideas [demanded by '&lt;i&gt;real&lt;/i&gt; users'] in the programming languages they do use."&lt;/p&gt;

&lt;p&gt;Finally, what the heck is up with "[u]sers of strongly typed languages demanded, and got, Lisp's heterogeneous lists." I'm not seeing it.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/GEtvK9Du1FU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/4138067610992041487/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=4138067610992041487" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/4138067610992041487?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/4138067610992041487?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/GEtvK9Du1FU/brian-harvey-on-scheme-vs-python.html" title="Brian Harvey on Scheme vs. Python" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/01/brian-harvey-on-scheme-vs-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUERXY-eCp7ImA9WhNaFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-242775515228436686</id><published>2013-01-25T12:59:00.002-06:00</published><updated>2013-01-30T14:03:24.850-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T14:03:24.850-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><category scheme="http://www.blogger.com/atom/ns#" term="protocols" /><title>RESTful web services</title><content type="html">&lt;p&gt;This is a copy of an email I just sent to a co-worker that I thought might be worth preserving.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I’m looking for a really good RESTful webservices book...."&lt;/p&gt;

&lt;p&gt;The three I have looked at are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;RESTful Web Services Cookbook&lt;/b&gt; by Subbu Allamaraju, is probably the one I would recommend. It follows the O'Reilly "cookbook" format, which I hate, but it has more specific details that aren't found in blog posts and product documentation.&lt;/li&gt;

&lt;li&gt;&lt;b&gt;RESTful Web Services&lt;/b&gt; by Leonard Richardson and Sam Ruby, is another one I would recommend. In fact, it is the more generic introduction to RESTy stuff, but since the devil is in the details, I kind of prefer the cookbook. On the other hand, if you're looking for two books, I would get both.&lt;/li&gt;

&lt;li&gt;&lt;b&gt;RESTful Java with JAX-RS&lt;/b&gt; by Bill Burke, which is focused primarily on the Java JSR-311/JAX-RS framework.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The one important blog post I would like to mention is Roy Fielding's "&lt;a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven"&gt;REST APIs must be hypertext-driven&lt;/a&gt;". Fielding produces exceptional gibberish, but that post has the three (really, two and a half) points that most RESTful stuff misses:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources...or in defining ... hypertext-enabled mark-up for existing standard media types." The important part of REST, as a networking strategy in general, is the focus on the "document", the messages exchanged on the wire describing the "resources". Almost everything else is actually an implementation detail that should be pinned down later.&lt;/li&gt;

&lt;li&gt;"A REST API must not define fixed resource names or hierarchies (an obvious coupling of client and server). Instead, allow servers to instruct clients on how to construct appropriate URIs, such as is done in HTML forms and URI templates, by defining those instructions within media types and link relations." Most of the REST documentation spends a lot of time on "URL paths", which is a complete waste of time since the client shouldn't care where the resources are.&lt;/li&gt;

&lt;li&gt;"A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience.... From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations...." This is a corollary of #2; every operation the client invokes 
should be driven from a URL received in a previous operation. The key point is that all the client needs to know is a single "touchpoint" URL and the format of the documents sent back and forth.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here endeth the lesson.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/SxS2kiipoj4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/242775515228436686/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=242775515228436686" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/242775515228436686?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/242775515228436686?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/SxS2kiipoj4/restful-web-services.html" title="RESTful web services" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2013/01/restful-web-services.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUAQX84fip7ImA9WhNaFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-2682336286119983743</id><published>2012-12-14T12:46:00.000-06:00</published><updated>2013-01-30T14:04:00.136-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T14:04:00.136-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="haskell" /><category scheme="http://www.blogger.com/atom/ns#" term="quote" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><title>Quote o' the day: The award for best function name goes to...</title><content type="html">&lt;p&gt;While reading a message from Daniel Fischer on the Haskell-beginners mailing list, what do I see but:&lt;/p&gt;

&lt;pre&gt;
it'sSafeIPromise :: Reader a -&gt; Text -&gt; a
it'sSafeIPromise = (value .)
  where
    value (Right (v,_)) = v

readInt :: Text -&gt; Int
readInt = it'sSafeIPromise decimal
&lt;/pre&gt;

&lt;p&gt;Yes, the apostrophe is a valid character in identifiers in Haskell, but I had always seen it as a prime, not in a contraction.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/dFjk_tMdIbQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/2682336286119983743/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=2682336286119983743" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2682336286119983743?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/2682336286119983743?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/dFjk_tMdIbQ/quote-o-day-award-for-best-function.html" title="Quote o' the day: The award for best function name goes to..." /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/12/quote-o-day-award-for-best-function.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUDQH89eyp7ImA9WhNaFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-8258737624382057485</id><published>2012-10-18T19:45:00.002-05:00</published><updated>2013-01-30T14:04:31.163-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T14:04:31.163-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="link" /><title>Link o' the day: Taken to School</title><content type="html">&lt;p&gt;From &lt;a href="http://dabacon.org/pontiff/"&gt;The Quantum Pontiff&lt;/a&gt;, a link to a journalistic investigation of the most important issue facing the academic community, not to mention the greatest scam ever perpetrated on the young people of today.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://dabacon.org/pontiff/?p=6541"&gt;Taken to School&lt;/a&gt;&lt;/p&gt;

&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/kWoQWoRjfGs" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/g6hnPBItETw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/8258737624382057485/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=8258737624382057485" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/8258737624382057485?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/8258737624382057485?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/g6hnPBItETw/link-o-day-taken-to-school.html" title="Link o' the day: Taken to School" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/kWoQWoRjfGs/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/10/link-o-day-taken-to-school.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQHQHszeyp7ImA9WhNaFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-7652861546215783560</id><published>2012-10-17T12:00:00.001-05:00</published><updated>2013-01-30T14:05:31.583-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T14:05:31.583-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="system administration" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><title>Tip: RedHat httpd RPM replacement</title><content type="html">&lt;p&gt;Hmph. I can't think of a word beginning with r- for Apache httpd.&lt;/p&gt;

&lt;p&gt;When a couple of our servers were patched, it looks like the RedHat httpd took over for our /usr/local/ httpd. I didn't think the RPM was installed previously but I'm not sure, so I don't know whether the infamous They upgraded it during the patching or if they just installed it.&lt;/p&gt;

&lt;p&gt;In any case, here's how to fix it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To tell what httpd is running:&lt;/p&gt;
&lt;pre&gt;
  $ ps -ef | grep httpd
&lt;/pre&gt;

&lt;p&gt;If the list of processes has /usr/sbin/httpd, it's the RPM version. Our local version will be something starting with /usr/local.&lt;/p&gt;
&lt;/li&gt;


&lt;li&gt;&lt;p&gt;If the RPM version is running, become root and kill it:&lt;/p&gt;

&lt;pre&gt;
  # /etc/init.d/httpd stop
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;(Optional) Blow away the httpd RPMs:&lt;/p&gt;

&lt;pre&gt;
  # rpm -qa | grep httpd
&lt;/pre&gt;

&lt;p&gt;This command lists the RPMs installed; looks like there's three on this server now: httpd-2.2.15, httpd-tools-2.2.15, and httpd-manual-2.2.15. (Yay, doccies.)&lt;/p&gt;

&lt;pre&gt;
  # yum remove &lt;i&gt;package&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;The &lt;package&gt; comes from the &lt;code&gt;rpm -qa&lt;/code&gt; list above, and removing httpd removes httpd-manual (and some other packages as well) so I just had to remove httpd and httpd-tools.&lt;/p&gt;

&lt;p&gt;That'll teach 'em.&lt;/p&gt;

&lt;p&gt;You will want to do this after you stop httpd and before you remove and re-create the /etc/init.d link because removing the RPM blows away the /etc/init.d link as well as stopping the server. Trying to use the &lt;code&gt;rpm&lt;/code&gt; command rather than &lt;code&gt;yum&lt;/code&gt; is possible (The command is &lt;code&gt;rpm -e &lt;i&gt;package&lt;/i&gt;&lt;/code&gt;.), but it doesn't remove recursive dependencies, meaning it will require iteration.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Remove the /etc/init.d/httpd script from the RPM and replace it with a link to the our version:&lt;/p&gt;

&lt;pre&gt;
  # rm /etc/init.d/httpd
  # ln -s /usr/local/&lt;i&gt;ours&lt;/i&gt;/httpd/bin/apachectl /etc/init.d/httpd
&lt;/pre&gt;

&lt;p&gt;Yes, the startup script that comes with apache is called &lt;code&gt;apachectl&lt;/code&gt;. If you removed the RPM in the previous step, you don't have to remove the init.d script here. If you didn't, you will probably have to go through this dance the next time They patch the servers.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Start our httpd:&lt;/p&gt;

&lt;pre&gt;
  # /etc/init.d/httpd start
&lt;/pre&gt;

&lt;p&gt;The ps command above should now show our httpd.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's to not having to look up &lt;i&gt;rpm&lt;/i&gt; commands again.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/9CUAjY71PMM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/7652861546215783560/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=7652861546215783560" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/7652861546215783560?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/7652861546215783560?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/9CUAjY71PMM/tip-redhat-httpd-rpm-replacement.html" title="Tip: RedHat httpd RPM replacement" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/10/tip-redhat-httpd-rpm-replacement.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQBSHw4eCp7ImA9WhNaFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-3582841997460172047</id><published>2012-09-18T11:50:00.000-05:00</published><updated>2013-01-30T14:05:59.230-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T14:05:59.230-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="quote" /><title>Quote o' the day: apt-wat?</title><content type="html">&lt;p&gt;From the &lt;a href="http://linux.die.net/man/8/apt-get"&gt;apt-get(8)&lt;/a&gt; man page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;remove&lt;/p&gt;
&lt;p style="margin-left: 2em;"&gt;remove is identical to install except that packages are removed instead of installed. Note the removing a package leaves its configuration files in system. &lt;b&gt;If a plus sign is appended to the package name (with no intervening space), the identified package will be installed instead of removed.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a burst of consistency, &lt;i&gt;apt-get install&lt;/i&gt; can remove packages: "If a hyphen is appended to the package name (with no intervening space), the identified package will be removed if it is installed." It also gives some explanation: "These latter features may be used to override decisions made by apt-get's conflict resolution system."&lt;/p&gt;

&lt;p&gt;Still, people think &lt;i&gt;I'm&lt;/i&gt; weird.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/YajdxUcHu2c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/3582841997460172047/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=3582841997460172047" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/3582841997460172047?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/3582841997460172047?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/YajdxUcHu2c/quote-o-day-apt-wat.html" title="Quote o' the day: apt-wat?" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/09/quote-o-day-apt-wat.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YHR3s5fCp7ImA9WhJUFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-1972574749536105286</id><published>2012-09-12T11:51:00.000-05:00</published><updated>2012-09-13T16:18:56.524-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-13T16:18:56.524-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quote" /><category scheme="http://www.blogger.com/atom/ns#" term="programming language" /><title>Quote o' the day: Slightly over the top</title><content type="html">&lt;p&gt;cunningjames, in the &lt;a href="http://www.reddit.com/r/programming/comments/zr5x0/go_a_good_proscons_at_conformal/"&gt;thread&lt;/a&gt; on &lt;a href="https://www.cyphertite.com/blog.php?/archives/7-Go-at-Conformal.html"&gt;Go at Conformal&lt;/a&gt; on proggit, &lt;a href="http://www.reddit.com/r/programming/comments/zr5x0/go_a_good_proscons_at_conformal/c674823"&gt;writes&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
Where are the cons? This reads to me like “Go is perfect! If my daughter brought home Go and told me she was having his baby, I’d be ecstatic! Yes, I know my daughter’s 11! Okay, the documentation is slightly less than perfect. But otherwise it’s the bee’s knees, the bee’s elbows, and — heck — all the bee’s hinge joints! Writing Go is like being on Vicodin and Cocaine and a mixture of adderall and benzos all the time!”
&lt;/blockquote&gt;

&lt;p&gt;Wow. Just, wow.&lt;p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/yO-PrbM9XbM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/1972574749536105286/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=1972574749536105286" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1972574749536105286?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1972574749536105286?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/yO-PrbM9XbM/quote-o-day-slightly-over-top.html" title="Quote o' the day: Slightly over the top" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/09/quote-o-day-slightly-over-top.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YFQXcyeCp7ImA9WhJUFUo.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-1570880900963638747</id><published>2012-08-18T22:26:00.000-05:00</published><updated>2012-09-13T16:18:30.990-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-13T16:18:30.990-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="link" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><title>Link o' the day: Why ebooks cost as much as paperbacks</title><content type="html">&lt;p&gt;From &lt;a href="http://www.wyrmis.com/index.html"&gt;Doug Bolden&lt;/a&gt;, &lt;a href="http://www.wyrmis.com/blots/2011/17/blot11318.html"&gt;Ten reasons why ebooks cost as much as paperbacks&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
10. High medical premiums associated with XML lung.
&lt;/blockquote&gt;

Cough, cough.&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/zaDItZH11Xo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/1570880900963638747/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=1570880900963638747" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1570880900963638747?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/1570880900963638747?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/zaDItZH11Xo/link-o-day-why-ebooks-cost-as-much-as.html" title="Link o' the day: Why ebooks cost as much as paperbacks" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/08/link-o-day-why-ebooks-cost-as-much-as.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YERH88eCp7ImA9WhJXFE4.&quot;"><id>tag:blogger.com,1999:blog-5087326709910512917.post-7517682162355598856</id><published>2012-07-27T17:07:00.000-05:00</published><updated>2012-08-08T08:05:05.170-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-08T08:05:05.170-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quote" /><title>Quote o' the day: IE vs. cookies</title><content type="html">From &lt;a href="http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx"&gt;EricLaw's IEInternals&lt;/a&gt;:

&lt;blockquote&gt;
It’s worth mentioning that increased cookie limit actually broke the website of a major financial institution. The site depended on cookies beyond the 20 cookie limit getting dropped, and stopped working properly when the limit was increased. This is just one example of how tightly-coupled today’s web is to IE’s cookie implementation. That, in turn, is one reason why the IE team must exercise great care when making any change to IE’s cookie implementation.
&lt;/blockquote&gt;

&lt;p&gt;Great care, indeed. Eric also writes, "Over the five years I’ve worked on Internet Explorer, I’ve probably seen more questions from the community about HTTP cookies than on any other topic."&lt;/p&gt;

&lt;p&gt;Which might mean something.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/crsr/nOWs/~4/BBURjcIn0us" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://maniagnosis.crsr.net/feeds/7517682162355598856/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5087326709910512917&amp;postID=7517682162355598856" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/7517682162355598856?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5087326709910512917/posts/default/7517682162355598856?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/crsr/nOWs/~3/BBURjcIn0us/quote-o-day-ie-vs-cookies.html" title="Quote o' the day: IE vs. cookies" /><author><name>Tommy McGuire</name><uri>https://plus.google.com/102334632004599133425</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FJ-DhlqLhm8/AAAAAAAAAAI/AAAAAAAAAGg/BlnUi7uESd0/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://maniagnosis.crsr.net/2012/07/quote-o-day-ie-vs-cookies.html</feedburner:origLink></entry></feed>
