<?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-19665561</id><updated>2011-04-21T18:07:25.500-04:00</updated><title type='text'>Jonathan's Techno-Tales</title><subtitle type='html'>No Magic - only tricks</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-19665561.post-2251740301082674275</id><published>2007-02-10T16:32:00.000-05:00</published><updated>2007-02-03T00:11:16.297-05:00</updated><title type='text'>Wordpress</title><content type='html'>I decided to migrate to wordpress.com for my blog.&lt;br /&gt;&lt;br /&gt;I initially copied all my blogger entries through the API. After a lot of fighting with the formatting, I concentrated on my entries (3) since January 1st, 2007.&lt;br /&gt;&lt;br /&gt;So, &lt;a href="http://technotales.wordpress.com/"&gt;this&lt;/a&gt; is where it happens now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-2251740301082674275?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/2251740301082674275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=2251740301082674275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/2251740301082674275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/2251740301082674275'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2007/02/wordpress.html' title='Wordpress'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-3551075038414091324</id><published>2007-02-02T22:30:00.000-05:00</published><updated>2007-02-03T00:11:16.329-05:00</updated><title type='text'>Ruby Streams</title><content type='html'>I've been thinking about my &lt;a href="/2007/01/story-of-businessdays.html"&gt;business days problem&lt;/a&gt; some more. And this time I turned to Ruby, a language which I am becoming quite familiar with.&lt;br /&gt;&lt;br /&gt;This is my naive implementation of streams in Ruby. Streams are thus functions. The actual class name is 'Proc', a lambda returns a 'Proc'. Each call returns a new value.&lt;code&gt;&lt;pre&gt;&lt;br /&gt;def stream_from(value)&lt;br /&gt;  lambda {value = value.succ}&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Proc&lt;br /&gt;  def filter&lt;br /&gt;    f = lambda do&lt;br /&gt;          value = self.call&lt;br /&gt;          return (yield(value) ? value : f.call)&lt;br /&gt;        end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def take(n)&lt;br /&gt;    result = []&lt;br /&gt;    n.times {result &lt;&lt; self.call}&lt;br /&gt;    return result&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;As for "filter", it takes a &lt;a href="http://en.wikipedia.org/wiki/Predicate_%28mathematics%29"&gt;predicate&lt;/a&gt; passed as block. The filter becomes a "decorator" for the stream.&lt;br /&gt;&lt;br /&gt;This is a nice example of closures. The 'value' parameters becomes the state for the stream. Also of note, the use of the variable 'f' to fake recursion of an anonymous function.&lt;br /&gt;&lt;br /&gt;Prints the 20 next business days:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;s = stream_from(Date.today).filter {|date| date.cwday &lt; 6}&lt;br /&gt;&lt;br /&gt;puts s.take(20)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Note that my "contract" with stream_from is that what I pass it implements succ. Here's an example with integer:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;s = stream_from(4)&lt;br /&gt;&lt;br /&gt;puts s.take(20)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;And, of course, filters can be chained. The next Monday that falls on a 17th:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;s = stream_from(Date.today).filter {|date| date.day == 17}.filter {|date| date.cwday == 1}&lt;br /&gt;&lt;br /&gt;puts s.call.to_s&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Here's the same code as before, but with a function cast as a block: &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;def monday?(date)&lt;br /&gt;  date.cwday == 1&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;s = stream_from(Date.today).filter {|date| date.day == 17}.filter(&amp;method(:monday?))&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I decided consciously to avoid optimizations here. It did keep my code short and clean. Besides, you should only optimize based on need.&lt;br /&gt;&lt;br /&gt;There's much &lt;a href="http://www.youtube.com/results?search_query=sicp+streams&amp;search=Search"&gt;more&lt;/a&gt; to streams... combining streams together, maps, more complicated generation of the next value, etc.&lt;br /&gt;&lt;br /&gt;So, here's your next interview questions: &lt;br /&gt;&lt;br /&gt;"What's the first 3 prime numbers after 5,000,000,000 which has a 3 as last digit?"&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;s = stream_from(5_000_000_000).filter{|x| x.prime?}.filter{|x| x.mod(10) == 3}&lt;br /&gt;&lt;br /&gt;puts s.take(3)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I leave the code for "prime?" to your imagination.&lt;br /&gt;&lt;br /&gt;The concept of command-line pipes springs to mind. One of the reason the command line is so powerful, is that you can combine filters together to perform truly complicated tasks. Another reason is that each filter does only one thing and does it well.&lt;br /&gt;&lt;br /&gt;It's all about thinking in pipes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-3551075038414091324?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/3551075038414091324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=3551075038414091324' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/3551075038414091324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/3551075038414091324'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2007/02/ruby-streams.html' title='Ruby Streams'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-7967059240657136769</id><published>2007-01-31T00:37:00.000-05:00</published><updated>2007-01-31T01:01:08.192-05:00</updated><title type='text'>The Story of business_days(...)</title><content type='html'>I've been really busy with work recently. However, while going over my requirements for the nth time, something caught my eye: business days.  In particular, finding the date 7 business days from a another date.&lt;br /&gt;&lt;br /&gt;Far from being a hard task, it fell more into the annoying category. Or maybe it would make for a good interview question. In the end, how complicated or simple can someone make such a function?&lt;br /&gt;&lt;br /&gt;A little background first. I had to use JavaScript, a language I'm only superficially familiar with. Also, after discussion with the customer, the definition of business days was Monday to Friday. No holidays are included... In fact, which holidays? And from what region/country?&lt;br /&gt;&lt;br /&gt;Having flirted with Haskell recently and being "influenced" by the &lt;a href="http://swiss.csail.mit.edu/classes/6.001/abelson-sussman-lectures/"&gt;SICP lectures&lt;/a&gt;, a few ideas came to mind.&lt;br /&gt;&lt;br /&gt;"business days" is a subset of "days", and both are infinitely lists. If I have a list of all the days and I filter it through the is_business_day(date) function, and I access the element at position 7, I get the answer. I was getting pretty angry with my inability to accomplish my task in such a straightforward way. I started to understand what people mean when they talk about the expressiveness of a programming language.&lt;br /&gt;&lt;br /&gt;I then turned to Ruby for ideas. The succ function came to mind, I made that my starting point.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;function include(value, list) {&lt;br /&gt;  for (var i=0; i &lt; list.length; i++) {&lt;br /&gt;    if(list[i] == value) return true;&lt;br /&gt;  };&lt;br /&gt;  return false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function succ(date) {&lt;br /&gt;  return new Date(date.getTime() + 1000 * 60 * 60 * 24);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function is_business_day(date) {&lt;br /&gt;  return include(date.getDay(), [1,2,3,4,5]); // mon-fri&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function business_succ(date) {&lt;br /&gt;  var result = succ(date);&lt;br /&gt;  return is_business_day(result) ? result : business_succ(result);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function repeat(f, x, n) {&lt;br /&gt;  if(n == 1)&lt;br /&gt;    return f(x);&lt;br /&gt;&lt;br /&gt;  return f(repeat(f, x, n-1));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function days(date, n) {&lt;br /&gt;  return repeat(succ, date, n);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function business_days(date, n) {&lt;br /&gt;  return repeat(business_succ, date, n);&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;Personally, the moment of enlightenment came when I realized that iterating for days or business days was the same code and that it could be made even &lt;em&gt;more&lt;/em&gt; generic by the repeat function.&lt;br /&gt;&lt;br /&gt;A few comments:&lt;ul&gt;&lt;li&gt;the include function would usually be borrowed from &lt;a href="http://prototypejs.org/api/enumerable/include"&gt;prototype.js&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;recursion has become part of my day-to-day programming techniques&lt;/li&gt;&lt;br /&gt;&lt;li&gt;all functional&lt;/li&gt;&lt;br /&gt;&lt;li&gt;definitely not the shortest code I've written, but all pieces are both trivial and reusable&lt;/li&gt;&lt;br /&gt;&lt;li&gt;a definite LISP-like flavor&lt;/li&gt;&lt;br /&gt;&lt;li&gt;proof that SICP and friends have been damaging my brain :)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-7967059240657136769?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/7967059240657136769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=7967059240657136769' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/7967059240657136769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/7967059240657136769'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2007/01/story-of-businessdays.html' title='The Story of business_days(...)'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-5989120632853728311</id><published>2007-01-04T10:45:00.000-05:00</published><updated>2007-01-04T11:51:56.521-05:00</updated><title type='text'>I didn't "get" bookmarklets</title><content type='html'>I have only recently been fully aware of the joys of &lt;a href="http://en.wikipedia.org/wiki/Bookmarklet"&gt;bookmarklets&lt;/a&gt;. Of course I had the &lt;a href="http://del.icio.us/help/buttons"&gt;del.icio.us bookmarklets&lt;/a&gt; for quite a while now, but, the idea had not fully sank in until recently. I didn't "get" bookmarklets.&lt;br /&gt;&lt;br /&gt;Yesterday I re-discovered &lt;a href="http://reader.google.com"&gt;Google Reader&lt;/a&gt; and with it came its own, very useful, bookmarklet: &lt;a href="javascript:var%20b=document.body;if(b){void(z=document.createElement('script'));void(z.src='http://www.google.com/reader/ui/subscribe-bookmarklet.js');void(b.appendChild(z));}else{location='http://www.google.com/reader/view/feed/'+encodeURIComponent(location.href)}"&gt;Subscribe...&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Today I decided to wrote my own: &lt;a href="javascript:location='http://booktrack.acidfog.com/books/add?text='+(/\d{10}/.exec(location)[0])"&gt;booktrack...&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Booktrack is a web application to keep track of the books I read. It keeps track of what I want to read, what I'm reading now and what I'm done reading. This was inspired by &lt;a href="http://www.librarything.com/"&gt;librarything.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When it came to data entry, I had integrated with the amazon search API and it was working great. However, when people talk about books they usually link directly to the entry at amazon. Being on the page and having to log into my application to look for the exact same book seemed like a task that could be automated.&lt;br /&gt;&lt;br /&gt;This was a spur-of-the-moment idea. A what-if that needed answering. 5 minutes later, I had it and it was working. It is relatively crude, but I'll take the iterative approach on this one.&lt;br /&gt;&lt;br /&gt;Now I'm wondering what else I could do with that? What else needs a bookmarklet? What have I missed? This is all part of me trying to keep an eye out for &lt;a href="http://jpalardy.blogspot.com/2006/11/automation-continued.html"&gt;stupid and repetitive tasks&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-5989120632853728311?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/5989120632853728311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=5989120632853728311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/5989120632853728311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/5989120632853728311'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2007/01/i-didnt-get-bookmarklets.html' title='I didn&apos;t &quot;get&quot; bookmarklets'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-116468208562182795</id><published>2006-11-27T21:38:00.000-05:00</published><updated>2006-11-27T21:48:05.640-05:00</updated><title type='text'>Useful: latest</title><content type='html'>I reinstalled my computer from the ground up recently.  This has given me a lot of opportunity to question, rethink and &lt;a href="http://jpalardy.blogspot.com/2006/11/automation-continued.html"&gt;automate&lt;/a&gt; my day-to-day activities.&lt;br /&gt;&lt;br /&gt;As part of my ongoing effort to redeploy my rails applications to my production environment in the most intelligent hands-off way, I've been looking for a way to "detect" the latest deployment.&lt;br /&gt;&lt;br /&gt;Here's the script that resulted:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;$VERBOSE = true&lt;br /&gt;&lt;br /&gt;pattern = ARGV[0]&lt;br /&gt;pattern ||= '*'&lt;br /&gt;&lt;br /&gt;latest = Dir.glob(pattern).sort_by {|f| File.mtime(f)}.last&lt;br /&gt;&lt;br /&gt;puts latest unless latest.nil?&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;It takes, optionally, a bash-style glob.  ( latest 'booktrack*' )&lt;br /&gt;&lt;br /&gt;I'm finding it surprisingly useful.  Let me know if it helps you out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-116468208562182795?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/116468208562182795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=116468208562182795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116468208562182795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116468208562182795'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/11/useful-latest.html' title='Useful: latest'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-116399285778789903</id><published>2006-11-19T21:42:00.000-05:00</published><updated>2006-11-19T22:20:57.860-05:00</updated><title type='text'>Automation - continued</title><content type='html'>It has been roughly a month since I started voluntarily &lt;a href="http://jpalardy.blogspot.com/2006/10/ruthless-automation.html"&gt;pushing the limits of automation&lt;/a&gt; in my life.  This has been mixed blessing.&lt;br /&gt;&lt;br /&gt;PROS:&lt;ul&gt;&lt;li&gt;medium to long -term quality of life is improved&lt;/li&gt;&lt;li&gt;helps me assimilate Ruby libraries&lt;br/&gt;(spending a lot of time on &lt;a href="http://gotapi.com"&gt;gotapi.com&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;CONS:&lt;ul&gt;&lt;li&gt;spending a fair amount of time automating&lt;/li&gt;&lt;li&gt;still facing the initial resistance to automation&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;h4&gt;A Story: Mac OS X Screenshots&lt;/h4&gt;3 words: CMD-SHIFT-4&lt;br /&gt;&lt;br /&gt;One of the joys of working with Mac OS X is the screenshot mechanism part of the OS.  Nothing to install, it is expected that you would want to take screenshots easily.  You type CMD-SHIFT-4, you get a crosshair, you select a region, then a file is created on your desktop.  Painless.&lt;br /&gt;&lt;br /&gt;CMD-SHIFT-4 takes care of the file creation, a mental block in process of saving a screenshot.  In the spirit of &lt;a href="http://www.amazon.com/dp/0321344758/"&gt;Don't Make Me Think&lt;/a&gt;, I can testify that one question I don't want to answer when taking a screenshot is "what filename should I save this as...?"  Imagine taking a picture with a camera and being asked to give it a filename...  I just want to save the screenshot, I will come back to it later.  In fact, I just want a long list of screenshots I take to be dumped somewhere, as a chronological series of things I found interesting.&lt;br /&gt;&lt;br /&gt;Mac OS X already takes care of incrementing the filename automatically.  Image 1.png, Image 2.png, etc...  That's great.  However, I was not so hot about the default "dumping" location.  So, naively, I created a folder called "dump" to which I would push the pictures when cleaning up.  What I had not fully absorbed was that I would have a filename conflict on my hands every time I did that.  If I had dumped a few screenshots to "dump", took a few more, and tried to push my files to "dump" again, chances would be very good I would have, for example, 2 files named "Image 1.png", the second one wanting to overwrite the first.&lt;br /&gt;&lt;br /&gt;Before I had become such a stickler for automation, I had decided to zip the pictures, name the file based on the date and push it to "dump".  This involved the manual steps of, selecting only the pictures on the desktop, selecting the "archive" option from the menu, finding out what was today's date, renaming the file in ISO style date format and moving the file to "dump".&lt;br /&gt;&lt;br /&gt;Today, while contemplating the mess that my desktop was becoming, I realized how badly in need of automation this process was.  So, 15 minutes of hacking later, I had a script that would select the pictures on the desktop (only the ones matching the screenshot naming convention), find out how many pictures I had moved so far (stored in a magic file in the destination directory), move the files while changing their names incrementally.  A little more work was involved in figuring out how to have automator run this script as a plugin.&lt;br /&gt;&lt;br /&gt;Now, I have what I wanted: screenshots stream.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/5054/487/1600/Picture%201.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/5054/487/400/Picture%201.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-116399285778789903?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/116399285778789903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=116399285778789903' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116399285778789903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116399285778789903'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/11/automation-continued.html' title='Automation - continued'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-116232478976965502</id><published>2006-10-31T14:12:00.000-05:00</published><updated>2006-10-31T14:59:49.836-05:00</updated><title type='text'>Revisited: Thinking versus doing</title><content type='html'>I've talked about this &lt;a href="http://jpalardy.blogspot.com/2006/07/thinking-versus-doing.html"&gt;before&lt;/a&gt;.  But &lt;a href="http://codecraft.info/index.php/archives/61/"&gt;Knowing, doing and learning&lt;/a&gt; puts it better.&lt;br /&gt;&lt;br /&gt;I liked this:&lt;br /&gt;&lt;blockquote&gt;...we really don’t know something until we use it. Understanding that we can’t really separate knowing from doing explains why people who love to code are so much better at it than those who don’t: they try stuff out.&lt;/blockquote&gt;&lt;br /&gt;And this:&lt;br /&gt;&lt;blockquote&gt;The cycle of learning is to learn a little, then use what you’ve learned, then learn some more.&lt;/blockquote&gt;&lt;br /&gt;Reinforces what I said, while being more articulate.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-116232478976965502?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/116232478976965502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=116232478976965502' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116232478976965502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116232478976965502'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/10/revisited-thinking-versus-doing.html' title='Revisited: Thinking versus doing'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-116140671585879276</id><published>2006-10-20T23:49:00.000-04:00</published><updated>2006-10-21T00:58:35.900-04:00</updated><title type='text'>Rails for fun</title><content type='html'>After months doing other projects at work, I've been "drafted" for some Java this week.  Specifically, I'm making a middleware servlet.  Since I knew I was going to do the Java-thing again, I bought &lt;a href="http://www.amazon.com/dp/0596005407/"&gt;Head First Servlets and JSP&lt;/a&gt;.  Like the others books in this series, it's really &lt;em&gt;really&lt;/em&gt; good.  Yes, I have mentioned this series &lt;a href="http://jpalardy.blogspot.com/2006/07/javascript-final-frontier.html"&gt;twice&lt;/a&gt; &lt;a href="http://jpalardy.blogspot.com/2006/06/remembering-kanjis.html"&gt;before&lt;/a&gt;, but rest assured that I am not getting any money from this.  People who know me know that I have trouble &lt;strong&gt;not&lt;/strong&gt; mentioning the things I love.&lt;br /&gt;&lt;br /&gt;Java is still not great, but it's not as bad as I remembered it to be.  And maybe it's the machines we have at work, but it feels insanely fast.  INSANELY fast.  But I digress.&lt;br /&gt;&lt;br /&gt;I've been programming in Rails for about a year now.  I have 4 fully-functional personal webapps to my count.   I also have &lt;a href="http://forkmapit.com/"&gt;forkmapit.com&lt;/a&gt; that I coded part of.  However, much of the credit goes to my friend &lt;a href="http://danieljohn.livejournal.com/"&gt;Daniel&lt;/a&gt;.   &lt;br /&gt;&lt;br /&gt;I eat my own dog food.  All the applications I developed, I use on a daily basis.  I coded my applications to solve actual problems that I was having.  Application development, however, is an iterative process.  You release something and your users tell you how close (or far) you are from what they thought they would get.  I am my own customer, and I am pretty demanding.  When you're forced to use your own application, you soon discover the annoyances and the many ways you could make it better.  Tonight, I hit the mental threshold where I decide to fix bugs, streamline and improve.&lt;br /&gt;&lt;br /&gt;After a week of Java, going back to Rails is a much needed break.  I code in Rails for fun.  Like myself, a lot of people using Rails have normal 9-to-5 jobs where they code in &lt;em&gt;whatever&lt;/em&gt; technology will ensure a regular paycheck.  In many ways, Rails is double-edges sword.  It's a pleasure to work with ... but a curse to those who have to "go back" to, say, Java for work.  I mentioned to coworkers that going back to Java after having used Ruby felt like having your hands tied behind your back and trying to program by typing with your nose...&lt;br /&gt;&lt;br /&gt;The application I was working on, I call "tvguide".  With "tvguide", I keep track of the episodes for the TV shows I watch.  It &lt;em&gt;was&lt;/em&gt; a plain application with a little bit of AJAX to update the numbers in a table.&lt;br /&gt;&lt;br /&gt;It &lt;em&gt;was&lt;/em&gt; a glorified spreadsheet.&lt;br /&gt;&lt;br /&gt;No more...  I implemented photo upload to the application, thumbnails for my listings, I completely changed (and improved!) the presentation, I took out pre-RJS DIY AJAX.  Best of all, I have a much better application now, with more features and LESS code.&lt;br /&gt;&lt;br /&gt;I want the tools I use to empower me.  Rails and Ruby are such tools.  As for "fun", I would say it's a side effect of using good tools.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-116140671585879276?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/116140671585879276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=116140671585879276' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116140671585879276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116140671585879276'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/10/rails-for-fun.html' title='Rails for fun'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-116125988482860753</id><published>2006-10-19T07:36:00.000-04:00</published><updated>2006-10-19T16:36:51.256-04:00</updated><title type='text'>Ruthless Automation</title><content type='html'>How many people truly use computers to automate repetitive daily tasks?  Even if they do, to what extent are they automating these tasks?&lt;br /&gt;&lt;br /&gt;I've always been a fan of automating boring and/or repetitive stuff out of my way, but I never conciously made an effort to automate all I &lt;em&gt;could&lt;/em&gt; automate.  That was until I read &lt;a href="http://steve.yegge.googlepages.com/saving-time"&gt;Saving Time&lt;/a&gt; and &lt;a href="http://www.pragmaticprogrammer.com/sk/auto/"&gt;Pragmatic Project Automation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I can think of 4 reasons for automating your tasks:&lt;ol&gt;&lt;li&gt;It forces you to really "understand" a task.  What am I exactly doing here?  Is there a better way?  Is this robust?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It &lt;em&gt;documents&lt;/em&gt; a task.  Not just a series of steps in your head anymore.  The script is the intent, the all encompassing series of steps you need to do combined with the things you need to "touch" to accomplish your tasks.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It saves times.  This one is obvious and is the most often presented reason.  I would dare say that taking 10 minutes to automate something that would have taken 5 minutes is still worth it.  Read on.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It hones your skills.  Makes you practice your soft-scripting skills&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;In light of #4, you can now see automation as an end rather than a means.&lt;br /&gt;&lt;br /&gt;Daily automation will expose you to a lot of small problems.  "How would I get the third column from that file?"  "How would I insert a line after a match in a file?"  "How many lines are in that file?"  "How many times is the word 'tomato' in that file?"  Note here that &lt;em&gt;everything&lt;/em&gt; is a file in UNIX, so these examples are more general than they appear.&lt;br /&gt;&lt;br /&gt;The more you automate, the better a programmer you become.  The better a programmer you are, the easier it is to automate.  You can also consider better understanding, better process documentation and time-saving as welcomed side-effects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-116125988482860753?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/116125988482860753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=116125988482860753' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116125988482860753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/116125988482860753'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/10/ruthless-automation.html' title='Ruthless Automation'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-115825536681760396</id><published>2006-09-14T13:13:00.000-04:00</published><updated>2006-09-14T13:36:06.890-04:00</updated><title type='text'>Mocking Ruby</title><content type='html'>No... not like it has been recently.&lt;br /&gt;&lt;br /&gt;The question came up of whether I had been using mock objects before and how I would do it in Ruby.  Having read recently &lt;a href="http://www.pragmaticprogrammer.com/starter_kit/utj/index.html"&gt;Pragmatic Unit Testing&lt;/a&gt;, I had a few ideas on how to proceed.  However, the rules change when you are using Ruby instead of Java.&lt;br /&gt;&lt;br /&gt;Here is the test code I answered my questions with:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;puts "before: #{Time.now}"&lt;br /&gt;&lt;br /&gt;class Time&lt;br /&gt;  def self.now&lt;br /&gt;    'mock answer'&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;puts "after:  #{Time.now}"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Outputs:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;before: Thu Sep 14 13:02:46 EDT 2006&lt;br /&gt;after:  mock answer&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No wrapper class.  No factories.&lt;br /&gt;&lt;br /&gt;For the sake of full disclosure: &lt;ul&gt;&lt;li&gt;You might want to save a pointer to the old method.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The way you would do that is a little &lt;a href="http://www.redhillconsulting.com.au/blogs/simon/archives/000326.html"&gt;cumbersome for static methods&lt;/a&gt; .  But it's very clean otherwise.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-115825536681760396?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/115825536681760396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=115825536681760396' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115825536681760396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115825536681760396'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/09/mocking-ruby.html' title='Mocking Ruby'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-115375376107794591</id><published>2006-07-24T11:01:00.000-04:00</published><updated>2006-07-24T14:11:15.466-04:00</updated><title type='text'>namei</title><content type='html'>I stumbled today on &lt;em&gt;namei&lt;/em&gt;, an executable found on Linux.  I'm not sure why I've never been exposed to it before, FreeBSD not packaging it comes to mind, but this is truly useful.  In a world of softlinks, with all their benefits and drawbacks, &lt;em&gt;namei&lt;/em&gt; follows the trail until it reaches a real end point.&lt;br /&gt;&lt;br /&gt;Here's a sample output on a RHEL box:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# namei `which java`&lt;br /&gt;f: /usr/bin/java&lt;br /&gt; d /&lt;br /&gt; d usr&lt;br /&gt; d bin&lt;br /&gt; l java -&gt; /etc/alternatives/java&lt;br /&gt;   d /&lt;br /&gt;   d etc&lt;br /&gt;   d alternatives&lt;br /&gt;   l java -&gt; /usr/lib/jvm/jre-1.4.2-gcj/bin/java&lt;br /&gt;     d /&lt;br /&gt;     d usr&lt;br /&gt;     d lib&lt;br /&gt;     d jvm&lt;br /&gt;     l jre-1.4.2-gcj -&gt; java-1.4.2-gcj-1.4.2.0/jre&lt;br /&gt;       d java-1.4.2-gcj-1.4.2.0&lt;br /&gt;       d jre&lt;br /&gt;     d bin&lt;br /&gt;     - java&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The best part is that I know exactly how this was coded ... and that I don't have to do it myself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-115375376107794591?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/115375376107794591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=115375376107794591' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115375376107794591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115375376107794591'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/07/namei.html' title='namei'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-115349486757229977</id><published>2006-07-21T11:08:00.000-04:00</published><updated>2006-07-21T11:57:51.106-04:00</updated><title type='text'>Thinking versus doing</title><content type='html'>Ever had the feeling that:&lt;ul&gt;&lt;li&gt;the task at hand would be easier if you mastered the topic more?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;you had researched a topic thoroughly but had nothing to show for it?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In the last few months, I've become more aware the tradeoffs required to program.  There is a constant battle between thinking and doing.  More importantly, there is a need to be careful about over-thinking and over-doing.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Thinking&lt;/th&gt;&lt;th&gt;Doing&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;research&lt;/li&gt;&lt;li&gt;RTFM&lt;/li&gt;&lt;li&gt;planning&lt;/li&gt;&lt;li&gt;designing&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;implementing&lt;/li&gt;&lt;li&gt;experimenting&lt;/li&gt;&lt;li&gt;practicing&lt;/li&gt;&lt;li&gt;typing (!)&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Pitfalls of "thinking" too much?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;less/no results&lt;/li&gt;&lt;li&gt;less/no practice&lt;/li&gt;&lt;li&gt;less/no hands-on experience to guide&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Pitfalls of "doing" too much?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;re-inventing the wheel&lt;/li&gt;&lt;li&gt;less than optimal solutions&lt;/li&gt;&lt;li&gt;less/no benefits from accepted best-practice (other people's mistakes)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The key is to &lt;strong&gt;constantly&lt;/strong&gt; switch modes.  Code a little bit, research a little bit, refactor/readjust your code, research with your newly acquired experience, and so on.&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;A typical scenario: ASCII downcast&lt;br /&gt;&lt;br /&gt;On one of the project I am working on, we ask for city names and display their peer-produced restaurant reviews.  The problem comes with cities like "Montréal" which contain accents.  We capture the string as UTF-8, that's not the problem.  Inserting it into a URL is another matter, although it works, it does make for ugly URLs: Montr%E9al.&lt;br /&gt;&lt;br /&gt;The problem becomes, how do I convert "Montréal" to "Montreal"?  More broadly, how do I remove all the accents?  This is something I call "ASCII downcast", I would be happy to learn the real name of this process -- it would surely guide my efforts towards a solution.&lt;br /&gt;&lt;br /&gt;Here are the steps I followed:&lt;ul&gt;&lt;li&gt;I googled for a few keywords&lt;br /&gt;(ruby, conversion, ASCII, UTF-8, downcast)&lt;/li&gt;&lt;li&gt;I researched the Ruby standard library&lt;br /&gt;(especially: Iconv)&lt;/li&gt;&lt;li&gt;I experimented a little bit in irb&lt;br /&gt;(utf-8 to ASCII, utf-8 to iso8859-1 to ASCII)&lt;/li&gt;&lt;li&gt;I googled for more keywords, including problem-specific keywords&lt;br /&gt;(e-acute, escape sequences)&lt;/li&gt;&lt;li&gt;I investigated the tr function of String&lt;/li&gt;&lt;li&gt;I researched tr and multi-byte encoding&lt;/li&gt;&lt;/ul&gt;Time elapsed: ~1 hour.&lt;br /&gt;&lt;br /&gt;This could have taken a LOT longer.  Consider that I'm already quite familiar with encodings, conversions, that I had sample files with the same content in multiple encodings, and that I knew the command-line versions of tr and iconv.&lt;br /&gt;&lt;br /&gt;The solution that I came up with is: &lt;ul&gt;&lt;li&gt;convert UTF-8 to ISO-8859-1 (raise exception if not possible)&lt;/li&gt;&lt;li&gt;use the tr function and map all accented characters to non-accented correspondent characters&lt;/li&gt;&lt;li&gt;manually map characters -- a one-shot investment&lt;/li&gt;&lt;li&gt;detect other "evil" characters (raise exception if needed)&lt;/li&gt;&lt;/ul&gt;It works, but it feels like a hack.  I feel like I'm missing a library somewhere that already does that.  I cannot believe that this problem has not been solved before and it implies I didn't do my research well enough.&lt;br /&gt;&lt;br /&gt;This reminds me of another similar situation I faced recently with Flickr-style tags.  We implemented a "naive" version of tags for the above mentioned projects only to find &lt;a href="http://dema.ruby.com.br/articles/2005/09/03/tagging-on-steroids-with-rails"&gt;this&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It was a learning experience, both coding it and being humbled by a better solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-115349486757229977?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/115349486757229977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=115349486757229977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115349486757229977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115349486757229977'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/07/thinking-versus-doing.html' title='Thinking versus doing'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-115323040134508391</id><published>2006-07-18T09:36:00.000-04:00</published><updated>2006-07-18T14:48:11.580-04:00</updated><title type='text'>JavaScript: The Final Frontier</title><content type='html'>While I was in California, I stopped by Borders to have a look.  I thought it would be bigger and more exciting.  But it was just another bookstore, much like the ones we already have in Montreal.  Incidentally, I did found a great bookstore a few days later: &lt;a href="http://www.digitalguru.com/"&gt;DigitalGuru&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;However, Borders had a sale on a few books, one of which was: &lt;a href="http://www.amazon.com/gp/product/0596102259"&gt;Head Rush AJAX&lt;/a&gt;.  I mentioned &lt;a href="http://jpalardy.blogspot.com/2006/06/remembering-kanjis.html"&gt;before&lt;/a&gt; that I have a great respect for the Head-First series.  I could complain that their books are quite verbose, but that's a small price to pay -- they drive the message across.&lt;br /&gt;&lt;br /&gt;Once, in high school, at the very beginning of the semester, our English (ESL) teacher told us to write an essay.  At the end of the semester, she asked us what we had learned this year.  We made a point to explain her that we didn't really learn anything and that it had been a waste of time.   We probably used gentler words though.  She took out the essays we had completely forgotten about.  She asked us to review them.  What a difference!  We cringed at the mistakes we had made, at our poor vocabulary, at our incredible lack of skills -- at least in comparison with our current level.  Thank you for opening my eyes, Mme Lacasse!&lt;br /&gt;&lt;br /&gt;It is too easy to think that we aren't improving because we lack the perspective of the before and after.&lt;br /&gt;&lt;br /&gt;When I closed the "Head Rush AJAX" book, I thought: "Thanks for nothing..." But I was mistaken.  Really mistaken.  I only realized afterwards, when faced with my first AJAX problem, that I understood the concepts and I knew what to do.  And I knew it wasn't like that before I had read the book.  There is skill in teaching without people realizing how much they are learning.&lt;br /&gt;&lt;br /&gt;Now I can play with AJAX, feed XML back in the requests and manipulate the DOM.  But JavaScript is one of the topics I don't master when it comes to web development.  I can "get by" but I definitely don't feel in control.  I am waiting anxiously for "Head First JavaScript" as hinted inside their last book.&lt;br /&gt;&lt;br /&gt;I could definitely go for more effortless learning.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-115323040134508391?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/115323040134508391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=115323040134508391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115323040134508391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115323040134508391'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/07/javascript-final-frontier.html' title='JavaScript: The Final Frontier'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-115046360399026411</id><published>2006-06-16T07:47:00.000-04:00</published><updated>2006-06-16T09:13:24.046-04:00</updated><title type='text'>Remembering Kanjis</title><content type='html'>A few years ago, I decided to learn another language.  English is not my first language and I remember fondly having to learn it.  Learning English had been fun and challenging.  It had also given me perspective on languages and thought processes.&lt;br /&gt;&lt;br /&gt;For various reasons, my non-obvious choice was: Japanese.  Japanese is an interesting language, but one of the most challenging aspect is definitively the writing systems.  Japanese consists of 3 writing systems: hiragana (Japanese phonetic characters), katakana (Japanese phonetic characters - used for foreign words) and kanji (Chinese characters).  Both hiragana and katakana contain 46 characters (or more, depending on how you count - the point is the order of magnitude) while kanji has ~50000 characters.  But, you &lt;em&gt;only&lt;/em&gt; need ~3300 to be a &lt;a href="http://mirrors.nihongo.org/www.hayamasa.demon.co.uk/afaq/how-many-kanjis.html"&gt;literate Japanese adult.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;How do you go about learning ~3300 characters?  Incidentally, maybe you don't... But you would be missing a whole part of the language.  It all depends on your level of involvement.&lt;br /&gt;&lt;br /&gt;I have seen too many too many books "throwing" Kanjis at me without a specific goal.  Flashing thousands of Kanjis in front of me will not help me learn them.  It's all about memory and learning techniques.  The correct associations must be created in your head to retain the data.  Some of the concepts I strongly believe in are explored &lt;a href="http://www.dsv.nl/~tom/Assint.htm"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yesterday, I picked up &lt;a href="http://www.amazon.com/gp/product/0804820384"&gt;A Guide to Remembering Japanese Characters&lt;/a&gt;.  Worth mentioning:&lt;ul&gt;&lt;li&gt;Detailed explanation of origins and meanings (interesting)&lt;/li&gt;&lt;li&gt;Suggestion for memorizing (mnemonic)&lt;/li&gt;&lt;li&gt;Components making up character (divide and conquer)&lt;/li&gt;&lt;li&gt;school level of the character (track your progress)&lt;/li&gt;&lt;/ul&gt;The amazing part is that it was the only book, at least in the language bookstore I was in, that was taking this approach!  I especially like the first point, learning &lt;em&gt;where&lt;/em&gt; the characters are from and &lt;em&gt;why&lt;/em&gt; the characters are like that -- which, to me, creates a whole new dimension to the problem.&lt;br /&gt;&lt;br /&gt;Another recent example for me was &lt;a href="http://www.amazon.com/gp/product/0596007124"&gt;Head First Design Patterns&lt;/a&gt; -- a really good book on patterns.  The introduction also explains a bit about why the book presents material the way it does: an interesting mix of "cognitive science, neurobiology, and educational psychology".  I think there is much of to be learned about "how" to teach rather than "what" to teach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-115046360399026411?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/115046360399026411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=115046360399026411' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115046360399026411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/115046360399026411'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/06/remembering-kanjis.html' title='Remembering Kanjis'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-114944110591051181</id><published>2006-06-04T12:11:00.000-04:00</published><updated>2006-06-04T13:11:54.046-04:00</updated><title type='text'>Doing GTD</title><content type='html'>It's been a while since I wrote.&lt;br /&gt;&lt;br /&gt;I've &lt;em&gt;actually&lt;/em&gt; been doing what's in &lt;a href="http://www.amazon.com/gp/product/0142000280/"&gt;Getting Things Done&lt;/a&gt;.  I started reading the book around Christmas and, ironically, it had been one of the things I couldn't get done.  I put the book aside when it started to explain the high-level view of how to get organized.  That would have been fine if I had &lt;em&gt;known&lt;/em&gt; that we would get into specifics in later chapters.&lt;br /&gt;&lt;br /&gt;When I finished the book, I knew what to do but there were 2 things I needed:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;to reread the appropriate sections&lt;/li&gt;&lt;li&gt;to set aside a whole day to do my inventory&lt;/li&gt;&lt;/ol&gt;That's what I did.  And I thought it was pretty painful. :)&lt;br /&gt;&lt;br /&gt;I went around my apartment and my car writing down every single thing that needed doing.  I tried not to "limit" my brainstorming, I wrote everything that sprung to mind.  It took me 2-3 hours and I collected ~200 items.&lt;br /&gt;&lt;br /&gt;At that point, I sat down and went &lt;em&gt;completely&lt;/em&gt; through my "inbox".  I decided on using plain .txt files and managing them with a &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; (of RoR fame) project.  Incidentally, I could go on and on about how great TextMate is, but that's not the subject of today's post.&lt;br /&gt;&lt;br /&gt;I ended up dividing my items into the following files:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;waiting for&lt;/li&gt;&lt;li&gt;agendas&lt;/li&gt;&lt;li&gt;at home&lt;/li&gt;&lt;li&gt;car&lt;/li&gt;&lt;li&gt;errands&lt;/li&gt;&lt;li&gt;phone&lt;/li&gt;&lt;li&gt;read/review&lt;/li&gt;&lt;li&gt;research&lt;/li&gt;&lt;li&gt;projects&lt;/li&gt;&lt;li&gt;someday&lt;/li&gt;&lt;/ul&gt;Tomorrow I'm doing my first weekly review and I might reorganize some of the categories.  For example, "research" and "at home" are messy right now and might turn into "at computer" and "at home" when I'm done cleaning them up.  I understand the need to "work" with the system a bit and iteratively make things better - I won't get it perfect the first time around.  Consequently, I accept to live in my imperfect system.&lt;br /&gt;&lt;br /&gt;I can testify that after you start using the system, your brain starts to trust it.  But it doesn't happen instantly either...  You keep checking your lists to see if you are not forgetting anything.  Then you start realizing that some lists don't need you to check them constantly.  Especially if you divided your actions appropriately.&lt;br /&gt;&lt;br /&gt;Things that I want to address are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;time required&lt;/li&gt;&lt;li&gt;energy needed&lt;/li&gt;&lt;/ul&gt;I already have "context" taken care of.  Maybe I also want to puts "tags" on my items.  We'll see...  that might require something more complicated than my current setup , and it might not be worth it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-114944110591051181?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/114944110591051181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=114944110591051181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114944110591051181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114944110591051181'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/06/doing-gtd.html' title='Doing GTD'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-114826355494833950</id><published>2006-05-21T21:01:00.000-04:00</published><updated>2006-05-21T22:19:47.553-04:00</updated><title type='text'>Ruby Exercises - Continued</title><content type='html'>It has been a few days since I forced myself to start coding in Ruby.  So far, it's been very rewarding.  I have been coding simple things that I had already coded before: towers of Hanoi, anagrams, reverse polish notation, primes "up to", great common divider, lowest common denominator, etc.  The whole point is not to learn new algorithms ... it's to learn Ruby.&lt;br /&gt;&lt;br /&gt;I have tried to become aware of my areas of uncertainty/darkness.  Whenever I code and I get this feeling that I am cutting corners or avoiding a problem, I take a moment to analyze my doubts.  This is all part of my new life philosophy I have adopted since I read: &lt;a href="http://folklore.org/StoryView.py?project=Macintosh&amp;story=Make_a_Mess,_Clean_it_Up!.txt"&gt;Make a Mess, Clean it Up!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Avoidance is easy.  It's easy to code "around" a problem rather than looking things up.  I have read about this recently: &lt;a href="http://www.plover.com/blog/prog/featurism.html"&gt;Creeping featurism and the ratchet effect&lt;/a&gt;.  I understand the argument for laziness.  But, I think there is also something else - something I would like to call "checkbox mentality".  &lt;br /&gt;&lt;br /&gt;This phenomenon occurs when you are working on a task and would like to finish it - to cross is off your list.  But, at some point during the execution of that task, you realize that the problem is more complicated than you thought.  As such, not only are you not done, you now have to divide your task in a collections of subtasks.&lt;br /&gt;&lt;br /&gt;Here is an example for something I worked on today.  I tried to put as many tasks as I could remember I did.  (photo exported from &lt;a href="http://freemind.sourceforge.net/wiki/index.php/Main_Page"&gt;FreeMind&lt;/a&gt; btw)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/5054/487/1600/rpn.0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/5054/487/400/rpn.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Everytime you subdivide your task, you create more work for yourself.  You create something that requires effort.&lt;br /&gt;&lt;br /&gt;I had to Google.  I had to go back to the &lt;a href="http://www.pragmaticprogrammer.com/titles/ruby/index.html"&gt;book&lt;/a&gt;.  Sometimes I had to go back for reference reasons.  Some other times, I had to go back because my brain did not register what I thought I had read and understood.  It's all part of learning.  It's all part of being a professional and striving for perfection.&lt;br /&gt;&lt;br /&gt;Now I know: if it hurts it's because I'm doing the right thing. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-114826355494833950?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/114826355494833950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=114826355494833950' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114826355494833950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114826355494833950'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/05/ruby-exercises-continued.html' title='Ruby Exercises - Continued'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-114822312656088792</id><published>2006-05-19T10:49:00.000-04:00</published><updated>2006-05-21T21:00:12.166-04:00</updated><title type='text'>Ruby Exercises</title><content type='html'>I have mentioned &lt;a href="http://jpalardy.blogspot.com/2006/05/learning-rails-and-ruby.html"&gt;before&lt;/a&gt; that I was in the process of reading &lt;a href="http://www.pragmaticprogrammer.com/titles/ruby/index.html"&gt;Programming Ruby (2nd edition)&lt;/a&gt;.  The more I read it, the more I love Ruby.&lt;br /&gt;&lt;br /&gt;However, as I have learned in the past, reading a book about a programming language does &lt;b&gt;NOT&lt;/b&gt; mean that I truly understand the depths of what I am reading.  Consequently, I have decided to come up with a series of exercises/drills/&lt;a href="http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Practices/Kata"&gt;katas&lt;/a&gt; to force me to use Ruby.&lt;br /&gt;&lt;br /&gt;Though I would like to come up with an actual list custom-designed for my needs, for the mean time I have decided just start programming and stop making excuses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-114822312656088792?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/114822312656088792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=114822312656088792' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114822312656088792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114822312656088792'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/05/ruby-exercises.html' title='Ruby Exercises'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-114822280128262587</id><published>2006-05-18T10:45:00.000-04:00</published><updated>2006-05-21T11:01:10.230-04:00</updated><title type='text'>Virtual Desktops</title><content type='html'>I had made a list of things to do this morning.  I sat down with my iBook -- ready to go.  Then I realized I needed to take care of something that I had been missing for a while: virtual desktops on Mac OS X.&lt;br /&gt;&lt;br /&gt;I thought I'd give Mac OS X's Exposé a chance and that installing a virtual desktop manager &lt;i&gt;might&lt;/i&gt; have prevented from fully understanding and/or appreciating Exposé.&lt;br /&gt;&lt;br /&gt;Don't get me wrong, I think Exposé is great.  But, to me, it's more of a "where's-that-window" feature than an organizational tool.  In contrast, virtual desktops do allow me to truly separate my windows into "concerns".  When I use virtual desktops, I usually set up as many as 10 virtual desktops: my development desktop (where I code), my "testing" desktop, my log-and-top desktop, my research desktop (Google), my email desktop, my "personal" desktop, and a few spare ones for other things that might come up but that I don't want to mix with everything else.&lt;br /&gt;&lt;br /&gt;A few people have commented on the overkill-ness of my setup.  It's definitely a new way to organize your work.  If virtual desktops are meant to (poorly) emulate multiple monitors, let me ask you this: What would you do differently if you had 2, 3, 5, 10 monitors?&lt;br /&gt;&lt;br /&gt;Virtual desktops create virtual screen real estate.  As a side-effect, they give you enough space to prevent you from "managing" your windows.  On each desktop you can create static spatial arrangement.  Once I open, resize and position a window, I barely touch it anymore.  In the same way that if you always put your stapler at the same place on your desk, you won't have to look for it and will probably be able to reach for it without even looking.  For me, the keyboard shortcuts become natural extensions to mental processes (I need to check the log =&gt; 3rd desktop =&gt; Command-Option-3) -- very little conscious thought is required, it becomes automatic.&lt;br /&gt;&lt;br /&gt;(Interesting idea: real world Exposé for the the stuff on your desk.  I guess that would be a very Matrix-like effect where you would throw all your stuff in the air, the moment would freeze, you pick your stapler and everything falls back exactly where it was)&lt;br /&gt;&lt;br /&gt;When you use Exposé, you have to make the mental effort of not only recognizing the things you are looking at (which is even harder for look-alike windows on your OS), but to track down their varying positions.  After all, Exposé does have the annoying tendency to change the position of the windows it displays based on an algorithm I don't fully understand.  Arguably, I shouldn't have to understand it either.&lt;br /&gt;&lt;br /&gt;So, I guess, for me, it's not just a question of screen real-estate.  It's a whole organizational system derived from spatial arrangement of different desktops and a contract with myself that the concern of a specific desktop is respected.  That is, that desktop 9 is where my email "lives" and that desktop 3 has my "tail -f" log terminal, "top" terminal and root privileges terminal at their respective positions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-114822280128262587?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/114822280128262587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=114822280128262587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114822280128262587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114822280128262587'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/05/virtual-desktops.html' title='Virtual Desktops'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19665561.post-114822264102441795</id><published>2006-05-15T10:42:00.000-04:00</published><updated>2006-06-16T09:16:01.040-04:00</updated><title type='text'>Learning Rails and Ruby</title><content type='html'>When was it again that the Ruby on Rails buzz started?  I remember watching the Quicktime video (it wasn't this one: &lt;a href="http://media.rubyonrails.org/video/rails_take2_with_sound.mov"&gt;Creating a weblog in 15 minutes&lt;/a&gt; - but it was very similar) and having that sinking feeling that I was missing something important.  I remember doing some research and trying to find the facts that would indicate that it was too good to be true.&lt;br /&gt;&lt;br /&gt;Then I decided to buy this book: &lt;a href="http://www.pragmaticprogrammer.com/titles/ruby/index.html"&gt;Programming Ruby (2nd edition)&lt;/a&gt;.  It was a setback.  Having programmed in Python for 3-4 years by then, I was resisting learning Ruby - a language similar yet different.  The examples from the early chapters didn't convince me enough to keep at it.  I put the book on hold for a while and pursued other interests.&lt;br /&gt;&lt;br /&gt;But Rails was always in the back of my mind.  I remember discussing it with some colleagues and "forcing" them to watch the video (hey, it's only 15 minutes, right?).  I did like to watch the look on their faces.&lt;br /&gt;&lt;br /&gt;I was doing some more Rails research when I came across an article which basically said, get this book: &lt;a href="http://www.pragmaticprogrammer.com/titles/rails/index.html"&gt;Agile Web Development with Rails&lt;/a&gt; and to come back to Ruby afterwards.  This was an important breakthrough in my Rails learning - I read the Rails book, learned Rails and was convinced to come back to Ruby -- I'm back on "Programming Ruby" these days ... it seems I get it now.&lt;br /&gt;&lt;br /&gt;This reminds me of this quote: "I see a lot of Rubyists worrying that Rails is stealing the show. Geez, folks, LET it steal the show." from Steve Yegge's &lt;a href="http://www.oreillynet.com/ruby/blog/2006/01/bambi_meets_godzilla.html"&gt;Bambi Meets Godzilla&lt;/a&gt;.  Rails was, for me, a major incentive to learn more about Ruby.  Not to say I wouldn't have gotten around to learning it anyway down the line...  but Rails just brought a lot of attention to the Ruby community.&lt;br /&gt;&lt;br /&gt;But one thing struck me last night as I was reading the book.  Ruby is both more and less complicated than Python.  For example, classes seem to be packed with more methods than Python, which seems like steepening the learning curve to me.  And the syntax doesn't always seem as clean as Python's (I never minded the forced indentation in Python - that took me 5 minutes to get used to).  And there's also these LISP reminiscent blocks and closures which I'm still trying to FULLY grasp.&lt;br /&gt;&lt;br /&gt;So, why does programming in Ruby seems so &lt;i&gt;natural&lt;/i&gt; then?&lt;br /&gt;&lt;br /&gt;I can think of 2 reasons right now:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;A lot of the minor annoyances I had when programming in other languages have been taking care of by Ruby.  The sum of all of the little nice things in Ruby do add to a lot.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;There is a "this-wasn't-slapped-together" feeling that I sometimes had in Java and even Python.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;I'll have to think about that some more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19665561-114822264102441795?l=jpalardy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jpalardy.blogspot.com/feeds/114822264102441795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19665561&amp;postID=114822264102441795' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114822264102441795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19665561/posts/default/114822264102441795'/><link rel='alternate' type='text/html' href='http://jpalardy.blogspot.com/2006/05/learning-rails-and-ruby.html' title='Learning Rails and Ruby'/><author><name>Jonathan</name><uri>http://www.blogger.com/profile/05210663066414703799</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://static.flickr.com/18/71219225_1b74ce52e6_o.jpg'/></author><thr:total>2</thr:total></entry></feed>
