<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6633693394553352212</id><updated>2011-04-21T16:39:16.883-07:00</updated><category term='Haskell'/><category term='Foibles'/><category term='textmate'/><category term='Functional Programming'/><category term='kGTD'/><category term='Ruby'/><category term='Rails'/><category term='Mac'/><title type='text'>Rubynations</title><subtitle type='html'>Ruminations on Ruby, Software Development, the Mac, Whatever</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-863124924398122599</id><published>2007-06-25T12:14:00.000-07:00</published><updated>2007-06-25T12:25:47.084-07:00</updated><title type='text'>Getting MySql Working Again with Rails</title><content type='html'>Over the last few days, and for no reason that I could identify, Rails started throwing numerous connection errors (on Mac OS X). This was quite frustrating, since I could not identify anything that had changed. Nevertheless, I opted to try to upgrade the Mysql driver to see if that would do the trick ( it had in the past).&lt;br /&gt;&lt;br /&gt;The first thing I did was upgrade Mysql to 5.0.41 from 5.0.14 or so. Easy peasy. Next, I upgraded the sql driver -&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;So far so good. So I kick off mongrel.....and BAM - get a string of errors, including &lt;/div&gt;&lt;br /&gt;&lt;code&gt;dyld: Library not loaded: /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After much googling, and not a little telling the ether what I thought of the whole matter, I found a &lt;a href="http://www.railsforum.com/viewtopic.php?pid=24070"&gt;solution&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo install_name_tool -change /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib &lt;br /&gt;      /usr/local/mysql/lib/libmysqlclient.15.dylib /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7/lib/mysql.bundle&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After this, no problems - and most importantly, the intermittent connection errors have stopped.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-863124924398122599?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/863124924398122599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=863124924398122599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/863124924398122599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/863124924398122599'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/06/getting-mysql-working-again-with-rails.html' title='Getting MySql Working Again with Rails'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-8900505371848538627</id><published>2007-05-15T12:55:00.000-07:00</published><updated>2007-05-15T13:12:00.076-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='textmate'/><title type='text'>Awk and Textmate - search and replace for LARGE files</title><content type='html'>Textmate is great, but it tends to choke when you do a search / replace operation on really large files. When it does not choke, it just takes a REALLY long time. Awk to the rescue. &lt;br /&gt;&lt;br /&gt;A common task (at least for me) is to update all the fields of a certain type in Rails fixture file. We have one for vehicle records that has around 1500 records, each averaging around 46 lines, for a total file length of around 69K lines. I tried replacing one field for each record (using a regex) in this file, and Textmate ground to a halt. &lt;br /&gt;&lt;br /&gt;Enter awk. Using Textmate's Filter Through Command, I performed the operation with one awk command. It took 3 seconds to complete.&lt;br /&gt;&lt;br /&gt;Here's how:&lt;br /&gt;1) open the file to be processed in Textmate&lt;br /&gt;2) Hit Command-Option R to invoke Filter Through Command...&lt;br /&gt;3) Enter your awk command, WITHOUT the filename. Mine was &lt;br /&gt;&lt;pre&gt;&lt;code&gt;awk '{ sub(/towed_at_date:.*/,"towed_at_date: &lt;%= Date.today %&gt;"); print }' &lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4) Select Input: Document, and Output: Replace Document in the dialog box&lt;br /&gt;5) Hit execute.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-8900505371848538627?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/8900505371848538627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=8900505371848538627' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/8900505371848538627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/8900505371848538627'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/05/awk-and-textmate-search-and-replace-for.html' title='Awk and Textmate - search and replace for LARGE files'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-5544495235778242458</id><published>2007-02-23T12:53:00.000-08:00</published><updated>2007-02-23T12:59:23.911-08:00</updated><title type='text'>Just once...</title><content type='html'>wouldn't it be nice if things just worked the &lt;b&gt;first&lt;/b&gt; time?&lt;br /&gt;So I decide to install Trac on Ubuntu. First time installing Ubuntu, but lo and behold, it just installed and worked. So far, so good. &lt;br /&gt;&lt;br /&gt;Then its time to install Trac. Good looking instructions. Looks like a no-brainer, which is good, because I am not in the mood for a 10 hour poking-around-all-over-the-damn-internet-looking-for-the-magic-missing-driver crap that I have had to do in the past with Linux. (I love linux, but you have to admit...)&lt;br /&gt;&lt;br /&gt;So I issue my first terminal command:&lt;br /&gt;&lt;br /&gt;sudo apt-get install trac libapache2-svn&lt;br /&gt;&lt;br /&gt;and I get&lt;br /&gt;&lt;br /&gt;"E: can't find trac' (not an exact quote, but you get the drift)&lt;br /&gt;&lt;br /&gt;The solution was easy (after a google search, of course...), but just once...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-5544495235778242458?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/5544495235778242458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=5544495235778242458' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/5544495235778242458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/5544495235778242458'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/02/just-once.html' title='Just once...'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-3527023651190173484</id><published>2007-01-30T11:27:00.000-08:00</published><updated>2007-01-30T11:43:51.545-08:00</updated><title type='text'>A Haskell Epiphanette</title><content type='html'>A link on reddit led me to this:&lt;br&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;I think it&amp;#8217;s important/useful to point out that &amp;#8220;program flow&amp;#8221; in a pure functional language is really a matter of data dependency. The compiler is only free to arbitrarily order computations if there are no data  dependencies. Furthermore, monads are not special in any way (they are after all just a useful set of combinators; &amp;#8230; &lt;strong&gt;they only wind up sequencing computations because they set up a data dependency between the two arguments of the bind operator&lt;/strong&gt;. &lt;br /&gt;  -Jeff [bold added by me]&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;I&amp;#8217;m a newbie to Haskell, and like all Haskell newbies, I&amp;#8217;m still working through the Monad fog. On the surface, they appeared to me to be not much more than a way to &lt;b&gt;cheat&lt;/b&gt; - to write in an imperative style in Haskell. So, I thought, if in the long run all you are &lt;em&gt;really&lt;/em&gt; doing in Haskell is writing a bunch of commands, just as you would in C++ or any other imperative language, then what&amp;#8217;s the point? Although you could argue that the net result is the same, i.e., you are effectively giving the computer a specific set of instructions to carry out, and in what order (basically), the quote above gave me a new perspective. Sometimes it just takes a little kick&amp;#8230;:-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-3527023651190173484?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/3527023651190173484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=3527023651190173484' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/3527023651190173484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/3527023651190173484'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/01/haskell-epiphanette.html' title='A Haskell Epiphanette'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-1479425203203620752</id><published>2007-01-26T08:31:00.000-08:00</published><updated>2007-01-26T16:04:07.927-08:00</updated><title type='text'>Rails Routing Errors: The "diff:{}" Problem</title><content type='html'>&lt;p&gt;Rails error messages are generally pretty good, but like anything, every once in a while you get one that just makes you go nuts. In creating a new section of our application, I decided to go the RESTy route and use the shiny new magic url thingies. To make life even more interesting, I used nested resources. In particular, I set up one route like this:&lt;/p&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;map.resources &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:calls&lt;/span&gt;, &lt;br /&gt;              &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:path_prefix&lt;/span&gt; =&amp;gt; &lt;span class="string string_quoted string_quoted_single string_quoted_single_ruby"&gt;'call_center'&lt;/span&gt;, &lt;br /&gt;              &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="string string_quoted string_quoted_single string_quoted_single_ruby"&gt;'call_center/calls'&lt;/span&gt;,&lt;br /&gt;              &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:member&lt;/span&gt; =&amp;gt; {&lt;span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"&gt; &lt;/span&gt;&lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:close&lt;/span&gt; =&amp;gt; &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:get&lt;/span&gt; } &lt;span class="keyword keyword_control keyword_control_ruby keyword_control_ruby_start-block"&gt;do &lt;/span&gt;|call|&lt;br /&gt;  call.resources &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:call_notes&lt;/span&gt;,&lt;br /&gt;                 &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="string string_quoted string_quoted_single string_quoted_single_ruby"&gt;'call_center/call_notes'&lt;/span&gt;,&lt;br /&gt;                 &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:new&lt;/span&gt; =&amp;gt; {&lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:add_note&lt;/span&gt; =&amp;gt; &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:post&lt;/span&gt;}&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Unfortunately, I immediately got this error when I tried to use my new route:&lt;/p&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;  &lt;span class="source source_ruby"&gt;add_note_new_call_note_url failed to generate from &lt;br /&gt;   {&lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:action&lt;/span&gt;=&amp;gt;&lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"add_note"&lt;/span&gt;, &lt;br /&gt;    &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:controller&lt;/span&gt;=&amp;gt;&lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"call_center/call_notes"&lt;/span&gt;},  &lt;br /&gt;  expected: &lt;br /&gt;   {&lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:action&lt;/span&gt;=&amp;gt;&lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"add_note"&lt;/span&gt;, &lt;br /&gt;    &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:controller&lt;/span&gt;=&amp;gt;&lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"call_center/call_notes"&lt;/span&gt;}, &lt;br /&gt;  --&gt; diff: {} &lt;-- &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice the last line: &lt;strong&gt;diff: {}&lt;/strong&gt;. So the difference between what the routing system got and what it wanted was&amp;#8230;.nothing. The answer, which I found after much gnashing of teeth, turned out to be really simple. I needed to add a parameter to the &lt;code&gt;add_note_new_call_note_url&lt;/code&gt;. The call that generated the error was&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;&lt;span class="source source_ruby"&gt;&amp;lt;% remote_form_for &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:call_note&lt;/span&gt;, &lt;br /&gt;                   &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:url&lt;/span&gt; =&amp;gt; add_note_new_call_note_url, ...&lt;/span&gt;&lt;br /&gt;                   &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What it &lt;em&gt;needed&lt;/em&gt; to be was&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;    &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:url&lt;/span&gt; =&amp;gt; add_note_new_call_note_url(&lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@call&lt;/span&gt;), ...&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The &lt;code&gt;@call&lt;/code&gt; provides the url generator with the correct context. I had seen (and used) this parameterized url helper in other places, but had not added it here. In fact, I'm still a little fuzzy on when exactly its needed, since some examples (even in AWDWR) don't use it and some do. At any rate, I now have a first place to look when I get this odd error message again. Lesson learned (I hope&amp;#8230;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-1479425203203620752?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/1479425203203620752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=1479425203203620752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/1479425203203620752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/1479425203203620752'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/01/rails-routing-errors-diff-problem.html' title='Rails Routing Errors: The &quot;diff:{}&quot; Problem'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-1840868782996689885</id><published>2007-01-21T17:29:00.000-08:00</published><updated>2007-01-21T17:47:09.815-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Suppressing link_to_if text when condition is false</title><content type='html'>The rails &lt;code&gt;link_to_if&lt;/code&gt; function is great for, well, creating a link if and only if a condition is true. The prototype is &lt;br/&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;     link_to_if(condition, &lt;br /&gt;            name, &lt;br /&gt;            options = {}, &lt;br /&gt;            html_options = {}, &lt;br /&gt;            *parameters_for_method_reference, &amp;amp;block)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Unfortunately, the default behavior is to put the link text on the page (with no link) if the condition is false. To rid yourself of the pesky text, so that &lt;em&gt;nothing&lt;/em&gt; shows up if the condition is false, just add an empty block&amp;#8230;&lt;br/&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;link_to_if(false, "Don't show me",a_fancy_url) {}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-1840868782996689885?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/1840868782996689885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=1840868782996689885' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/1840868782996689885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/1840868782996689885'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/01/suppressing-linktoif-text-when.html' title='Suppressing link_to_if text when condition is false'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-7769337163535518149</id><published>2007-01-21T10:07:00.000-08:00</published><updated>2007-01-27T14:20:38.159-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='kGTD'/><title type='text'>Bye Quicksilver, for now at least</title><content type='html'>&lt;p&gt;I was introduced to &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt; last year by someone at the Rails user group. I&amp;#8217;m not sure how I survived on the Mac without it. I used it for launching apps, appending to files, and jotting quick notes that went straight to &lt;a href="http://www.kinkless.com/"&gt;kGTD&lt;/a&gt;. Incredible productivity booster.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;And I just quit using it, and bought &lt;a href="http://www.obdev.at/products/launchbar/index.html"&gt;LaunchBar&lt;/a&gt;. Why? Stability. QS is great, but it crashes &lt;em&gt;frequently&lt;/em&gt; - sometimes 5 or 6 times a day. For no apparent reason. Yes, I know its beta. Yes, I know its free. Yes,yes,yes. LaunchBar is more limited, yes, but it is rock solid. And &lt;em&gt;fast&lt;/em&gt;. Seemingly faster than QS (although I have not measured it in any way&amp;#8230;). If I can find a script that lets me access kGTD from LaunchBar, it may be a permanent replacement. (The only one I&amp;#8217;ve found so far seemed to have a problem on the download page)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;UPDATE: ..not that anybody but me really cares... :-)&lt;br /&gt;Going to stick with LaunchBar. No crashes, fast, and the advanced kgtd script works with the new version of LaunchBar as easily as it did with quicksilver.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-7769337163535518149?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/7769337163535518149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=7769337163535518149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/7769337163535518149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/7769337163535518149'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/01/bye-quicksilver-for-now-at-least.html' title='Bye Quicksilver, for now at least'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-5514192772868357383</id><published>2007-01-19T19:09:00.000-08:00</published><updated>2007-01-20T09:52:40.332-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Foibles'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Accidentally accessing accessors in Ruby</title><content type='html'>&lt;p&gt;I spent about 30 minutes today trying to determine if I had been misunderstanding &lt;strong&gt;basic&lt;/strong&gt; Ruby syntax for more than a year, or if I had just discovered an undocumented bug in the language. The answer was neither, of course. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Ruby variable naming is straightforward. Class instance variables begin with &lt;code&gt;@&lt;/code&gt;, as in &lt;code&gt;@user_name&lt;/code&gt;. Local variables are unadorned - just &lt;code&gt;user_name&lt;/code&gt;. So, when I came across some code that a co-worker had written that did not follow this convention, and he said that it was working fine, I was initially confused. Here&amp;#8217;s an extremely simplified example:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    1&lt;/span&gt; &lt;span class="source source_ruby"&gt;&lt;span class="declaration declaration_class declaration_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_class entity_name_class_ruby"&gt;VarTest&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    2&lt;/span&gt;   &lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;attr_accessor&lt;/span&gt; &lt;span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;:instance_var&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    3&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;    4&lt;/span&gt; &lt;span class="declaration declaration_function declaration_function_method declaration_function_method_without-arguments declaration_function_method_without-arguments_ruby"&gt;  &lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;print_it&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    5&lt;/span&gt;     puts &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"The instance var is &lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{instance_var}&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    6&lt;/span&gt;   &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    7&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;    8&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    9&lt;/span&gt; &lt;br /&gt;&lt;span class='linenum'&gt;   10&lt;/span&gt; vt = &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;VarTest&lt;/span&gt;.&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   11&lt;/span&gt; vt.instance_var = &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"fred"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   12&lt;/span&gt; vt.print_it&lt;br /&gt;&lt;/span&gt;&lt;span class='linenum'&gt;   13&lt;/span&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This code should be spitting out something about the invalid use of the instance variable &lt;code&gt;instance_var&lt;/code&gt;, right? That should be &lt;code&gt;@instance_var&lt;/code&gt; in that method (line 5). But there it was, working just fine.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So I experimented a bit.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    1&lt;/span&gt; &lt;span class="source source_ruby"&gt;&lt;span class="declaration declaration_class declaration_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_class entity_name_class_ruby"&gt;VarTest&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    2&lt;/span&gt;   &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@instance_var&lt;/span&gt; = &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"some initial value"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    3&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;    4&lt;/span&gt; &lt;span class="declaration declaration_function declaration_function_method declaration_function_method_without-arguments declaration_function_method_without-arguments_ruby"&gt;  &lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;print_it&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    5&lt;/span&gt;     puts &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"The instance var is &lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{instance_var}&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    6&lt;/span&gt;   &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    7&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;    8&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    9&lt;/span&gt; &lt;br /&gt;&lt;span class='linenum'&gt;   10&lt;/span&gt; vt = &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;VarTest&lt;/span&gt;.&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   11&lt;/span&gt; vt.print_it&lt;br /&gt;&lt;span class='linenum'&gt;   12&lt;/span&gt; &lt;br /&gt;&lt;span class='linenum'&gt;   13&lt;/span&gt; &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;# ~&amp;gt; -:5:in `print_it': undefined local variable or method `instance_var' for #&amp;lt;VarTest:0x1d4558&amp;gt; (NameError)&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   14&lt;/span&gt; &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;# ~&amp;gt;  from -:11&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class='linenum'&gt;   15&lt;/span&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now &lt;strong&gt;that&amp;#8217;s&lt;/strong&gt; what I had expected the first time. After more moments of confusion than I really care to admit, the extremely obvious answer came to me. In the first example, &lt;code&gt;instance_var&lt;/code&gt; was the &lt;em&gt;accessor method&lt;/em&gt;, NOT the variable. Duh. In the second example, where the error was thrown, &lt;code&gt;instance_var&lt;/code&gt; &lt;em&gt;was&lt;/em&gt; a local variable, since no accessor had been declared. Hence, the error. Again, duh.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;It does bring up an interesting point, however. When I am accessing an instance variable from within a method, I use &lt;code&gt;@varname&lt;/code&gt;, never just &lt;code&gt;varname&lt;/code&gt;. But, I also frequently create accessor methods in Rails models that manipulate the data in some way. This leads to the possibility of some interesting bugs. Here&amp;#8217;s a pretty contrived example.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    1&lt;/span&gt; &lt;span class="source source_ruby"&gt;&lt;span class="declaration declaration_class declaration_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_class entity_name_class_ruby"&gt;User&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    2&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;    3&lt;/span&gt; &lt;span class="declaration declaration_function declaration_function_method declaration_function_method_with-arguments declaration_function_method_with-arguments_ruby"&gt;  &lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;lastname=&lt;/span&gt;(&lt;span class="variable variable_parameter"&gt;val&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    4&lt;/span&gt;     &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@lastname&lt;/span&gt; = val&lt;br /&gt;&lt;span class='linenum'&gt;    5&lt;/span&gt;   &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    6&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;    7&lt;/span&gt; &lt;span class="declaration declaration_function declaration_function_method declaration_function_method_without-arguments declaration_function_method_without-arguments_ruby"&gt;  &lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;lastname&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    8&lt;/span&gt;     &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"Mr. "&lt;/span&gt; + &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@lastname&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;    9&lt;/span&gt;   &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   10&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;   11&lt;/span&gt; &lt;span class="declaration declaration_function declaration_function_method declaration_function_method_without-arguments declaration_function_method_without-arguments_ruby"&gt;  &lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;print_name&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   12&lt;/span&gt;     puts &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"print_name: &lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{lastname}&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   13&lt;/span&gt;   &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   14&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;   15&lt;/span&gt; &lt;span class="declaration declaration_function declaration_function_method declaration_function_method_without-arguments declaration_function_method_without-arguments_ruby"&gt;  &lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;print_name2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   16&lt;/span&gt;     puts &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"print_name2: &lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{&lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@lastname&lt;/span&gt;}&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   17&lt;/span&gt;   &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   18&lt;/span&gt;   &lt;br /&gt;&lt;span class='linenum'&gt;   19&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   20&lt;/span&gt; &lt;br /&gt;&lt;span class='linenum'&gt;   21&lt;/span&gt; vt = &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;User&lt;/span&gt;.&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   22&lt;/span&gt; vt.lastname = &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"Kruger"&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   23&lt;/span&gt; vt.print_name&lt;br /&gt;&lt;span class='linenum'&gt;   24&lt;/span&gt; vt.print_name2&lt;br /&gt;&lt;span class='linenum'&gt;   25&lt;/span&gt; &lt;br /&gt;&lt;span class='linenum'&gt;   26&lt;/span&gt; &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;# &amp;gt;&amp;gt; print_name: Mr. Kruger&lt;/span&gt;&lt;br /&gt;&lt;span class='linenum'&gt;   27&lt;/span&gt; &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;# &amp;gt;&amp;gt; print_name2: Kruger&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class='linenum'&gt;   28&lt;/span&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is fine, and correct of course, unless what I &lt;strong&gt;really&lt;/strong&gt; wanted was &amp;#8220;Mr. Kruger&amp;#8221; in both cases. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2 id="the_lesson_here_is8230"&gt;The lesson here is&amp;#8230;&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The only real lesson is to be aware of the difference between using @ and not in class methods. Best practice is probably to consistently use @, in part simply because it helps differentiate between local and instance variables. In cases where the accessor really needs to be used, as when the accessor function is performing some sort of processing, its best to use &lt;code&gt;self.varname&lt;/code&gt; to make it clear that a function is being called.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-5514192772868357383?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/5514192772868357383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=5514192772868357383' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/5514192772868357383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/5514192772868357383'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/01/accidentally-accessing-accessors-in.html' title='Accidentally accessing accessors in Ruby'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-4485196190115250636</id><published>2007-01-01T09:49:00.000-08:00</published><updated>2007-01-02T15:29:50.163-08:00</updated><title type='text'>New blog</title><content type='html'>Just moved this from the free wordpress.com account, since it lets me change the CSS without paying a fee :-). The entry &lt;a href="http://rubynations.blogspot.com/2006/12/html.html"&gt;Evolution:: (Rails,Ruby) -&gt; Haskell&lt;/a&gt; appeared on the wordpress site initially, and was refd on reddit. The version here has some updates based on feedback from some folks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-4485196190115250636?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/4485196190115250636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=4485196190115250636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/4485196190115250636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/4485196190115250636'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2007/01/new-blog.html' title='New blog'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6633693394553352212.post-4305851669529656838</id><published>2006-12-28T14:11:00.000-08:00</published><updated>2007-01-02T10:53:08.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Functional Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Evolution:: (Rails,Ruby) -&gt; Haskell</title><content type='html'>Apparently, there is a renewed / growing interest in functional languages like &lt;a href="http://www.haskell.org"&gt;Haskell&lt;/a&gt;, OCaml, etc. and I am again being accidentally trendy... :-). Here's a bit on how I managed to stumble upon Haskell and how its affecting me as a developer...&lt;br /&gt;&lt;br /&gt;Last year, along with thousands of others, I discovered Ruby on Rails, and built the core product for my &lt;a href="http://www.compiledlogic.com"&gt;company&lt;/a&gt; using it. It was (and continues to be) a great programming experience. Like everyone else who uses Rails for more than a couple of minutes, I fell in love with Ruby as a programming language. Coming from a background in C/C++ yada yada, Ruby opened up this wonderful world of blocks, closures, lambdas, etc. - concepts that despite 25+ years of programming were new to me. I was so excited, in fact, that I ended up helping to create the Houston Ruby on Rails user group.&lt;br /&gt;&lt;br /&gt;Since most of the Rails group members came from similar backgrounds to mine, none of us really had anything more than a superficial understanding the whole lambda thing, so I was elected to give a talk on it. It was in doing my research for the presentation that I came across &lt;a href="http://en.wikipedia.org/wiki/Functional_programming"&gt;functional programming (FP)&lt;/a&gt; and Haskell.&lt;br /&gt;&lt;br /&gt;I've just begun to scratch the surface of Haskell and FP, but its already changed the way I think about things in Ruby. I've been doing OOAD for many, many years, and I approach Ruby from that perspective. I tend to think in terms of OO abstractions, and methods on classes that alter state, i.e., alter the values of variables in an object. In FP, and Haskell in particular since it is the "purest" of the FP languages, there is no such thing (ignoring &lt;a href="http://en.wikipedia.org/wiki/Monads_in_functional_programming"&gt;monads&lt;/a&gt; for the time being) as state. "Variables" are really more like constants in other languages - you can assign (aka bind) values to them, but that's it. Functions in FP take inputs and produce outputs, with no "&lt;a href="http://en.wikipedia.org/wiki/Side_effect_%28computer_science%29"&gt;side effects&lt;/a&gt;", meaning that they do not alter state or global variables. Since variables can only be assigned to once (like constants), new approaches are required for just about everything. The simplest example is iterating over a collection. In C++, you just do something like &lt;br /&gt; &lt;pre class="textmate-source"&gt;&lt;span class="source source_c"&gt;&lt;span class="storage storage_type storage_type_c"&gt;int&lt;/span&gt; x[&lt;span class="constant constant_numeric constant_numeric_c"&gt;3&lt;/span&gt;] = {&lt;span class="constant constant_numeric constant_numeric_c"&gt;1&lt;/span&gt;,&lt;span class="constant constant_numeric constant_numeric_c"&gt;2&lt;/span&gt;,&lt;span class="constant constant_numeric constant_numeric_c"&gt;3&lt;/span&gt;}&lt;br /&gt; &lt;span class="keyword keyword_control keyword_control_c"&gt;for&lt;/span&gt;(&lt;span class="storage storage_type storage_type_c"&gt;int&lt;/span&gt; i = &lt;span class="constant constant_numeric constant_numeric_c"&gt;0&lt;/span&gt;; i &amp;lt; &lt;span class="constant constant_numeric constant_numeric_c"&gt;2&lt;/span&gt;; ++i)&lt;br /&gt;{&lt;br /&gt;  x[i] = x[i] * &lt;span class="constant constant_numeric constant_numeric_c"&gt;2&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt; &lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;and you're done. This can't be done in Haskell, since you would be reassigning values to the variable &lt;strong&gt;i&lt;/strong&gt;. &lt;em&gt;UPDATE: For the sake of clarity, I am &lt;strong&gt;not&lt;/strong&gt; trying to say that you can't iterate in this style - but rather that incrementing a variable (i++) is not allowed in Haskell (although I understand that there are monadic ways of doing this?).&lt;/em&gt; In Haskell, you would use a function (map) that applies another function (*2 in this case) to each element in the array or list (&lt;strong&gt;x&lt;/strong&gt; in this case), like this:&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;span class="source source_haskell"&gt;&lt;span class="entity entity_name entity_name_function entity_name_function_builtin entity_name_function_builtin_prelude entity_name_function_builtin_prelude_haskell"&gt;map&lt;/span&gt; (*2) [1,2,3]&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;I'm fudging slightly here - the C++ example is of an array, while the Haskell example is really a list. The concept is the same, though.&lt;br /&gt;&lt;br /&gt;There are many new concepts in Haskell and FP that I intend to explore over time, but how has this one aspect changed my Ruby programming? I already used Ruby iterators (such as map, inject, etc.) with associated blocks to manipulate arrays. But I also used &lt;strong&gt;x.each&lt;/strong&gt; frequently, essentially taking the same approach that I might have using C. This is not bad, of course, however the FP approach made me take a second look at some of the code that used that idiom, and I quickly realized that I was &lt;br&gt;&lt;br /&gt;(a) not taking full advantage of the Ruby higher level iterators such as &lt;strong&gt;map&lt;/strong&gt;, and &lt;br&gt;&lt;br /&gt;(b) creating local variables all over the place, sometimes without a very good &lt;br /&gt;reason.&lt;br /&gt;&lt;br /&gt;Local variables aren't bad either, &lt;em&gt;per se&lt;/em&gt;, of course. Sometimes they simply help make the code more readable and easier to debug. But every line of code has a potential for creating a bug, so there is a balance to be sought. So......here's an example of some code from our application that I reworked based on my new found FP sensibilities...&lt;br /&gt;&lt;br /&gt;The original code:&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;span class="source source_ruby"&gt;html.each &lt;span class="keyword keyword_control keyword_control_ruby keyword_control_ruby_start-block"&gt;do &lt;/span&gt;|line|&lt;br /&gt;  &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@search_terms&lt;/span&gt;.each &lt;span class="keyword keyword_control keyword_control_ruby keyword_control_ruby_start-block"&gt;do &lt;/span&gt;|term| &lt;br /&gt;    line.gsub!(&lt;span class="string string_regexp string_regexp_classic string_regexp_classic_ruby"&gt;/&lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{term}&lt;/span&gt;/i&lt;/span&gt;,&lt;span class="string string_quoted string_quoted_single string_quoted_single_ruby"&gt;'&amp;lt;span class="found_text"&amp;gt;;\&amp;amp;&amp;lt;/span&amp;gt;'&lt;/span&gt;) &lt;span class="keyword keyword_control keyword_control_ruby"&gt;unless&lt;/span&gt; line =~&lt;span class="string string_regexp string_regexp_classic string_regexp_classic_ruby"&gt; /&lt;span class="string string_regexp string_regexp_group string_regexp_group_ruby"&gt;(&amp;lt;|Storage|Towslip)&lt;/span&gt;/&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;@results_html&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This of course is not bad, and is pretty readable. The general structure is to iterate over each line, then each term, and do a global substitution using a regex. Each line is modified in place using "gsub!". For each term, though, there are actually (potentially) two regex calls - one to determine if the line should be modified, and the other to search for terms to modify. So how would I approach it from a more FP point of view? This is admittedly a naive approach, but just thinking "How could I treat the html as whole and NOT modify values (as in the line.gsub! call)?" proved interesting. The result is below. The regexs are combined into one making it more efficient (although for the non-regex initiated it may seem pretty messy). There are NO explicit intermediate variables.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source"&gt;&lt;span class="source source_ruby"&gt;&lt;span class="declaration declaration_function declaration_function_method declaration_function_method_with-arguments declaration_function_method_with-arguments_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;highlight_html&lt;/span&gt;(&lt;span class="variable variable_parameter"&gt;html,ht, et&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;  html.map &lt;span class="keyword keyword_control keyword_control_ruby keyword_control_ruby_start-block"&gt;do &lt;/span&gt;|line|&lt;br /&gt;    line.gsub(&lt;span class="string string_regexp string_regexp_classic string_regexp_classic_ruby"&gt;/&lt;span class="string string_regexp string_regexp_group string_regexp_group_ruby"&gt;(?!&lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{et.join(&lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"|"&lt;/span&gt;)}&lt;/span&gt;)&lt;/span&gt;&lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{ht.join(&lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"|"&lt;/span&gt;)}&lt;/span&gt;/i&lt;/span&gt;) \&lt;br /&gt;             {&lt;span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"&gt; &lt;/span&gt;|m| &lt;span class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;"&amp;lt;span class='found_text'&amp;gt;&lt;span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;#{m}&lt;/span&gt;&amp;lt;/span&amp;gt;"&lt;/span&gt; }&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;.to_s&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Some good references&lt;/p&gt;&lt;br /&gt; &lt;a href="http://www-128.ibm.com/developerworks/java/library/j-cb07186.html"&gt;Exploring functional programming, Bruce Tate&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6633693394553352212-4305851669529656838?l=rubynations.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubynations.blogspot.com/feeds/4305851669529656838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6633693394553352212&amp;postID=4305851669529656838' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/4305851669529656838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6633693394553352212/posts/default/4305851669529656838'/><link rel='alternate' type='text/html' href='http://rubynations.blogspot.com/2006/12/html.html' title='Evolution:: (Rails,Ruby) -&gt; Haskell'/><author><name>Keith Lancaster</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>
