<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3837840012614392958</atom:id><lastBuildDate>Wed, 06 Mar 2013 18:03:11 +0000</lastBuildDate><category>Unix</category><category>Shoes</category><category>Rails plugin</category><category>Ruby quiz (easy)</category><category>Javascript</category><category>books</category><category>Rails</category><category>railsconf 2009</category><category>Ruby quiz (intermediate)</category><category>projects</category><category>context</category><category>Ruby1.9</category><category>Sinatra</category><category>OSX</category><category>pdf</category><category>presentation</category><category>Unix permissions</category><category>RSpec</category><category>JRuby</category><category>git</category><category>Ruby</category><category>Rails performance</category><category>tips</category><category>functional programming</category><category>doing cool stuff</category><category>monkey-patching</category><category>Rails podcast</category><category>Ruby metaprogramming</category><category>scrubyt</category><category>Ubuntu</category><category>testing</category><category>architecture</category><category>MRI</category><category>Ruby quiz (advanced)</category><title>Dev logger</title><description>Crumbs of a programmer, with an interest mostly in Ruby, Rails and Linux.</description><link>http://dev-logger.blogspot.com/</link><managingEditor>noreply@blogger.com (Martin Carel)</managingEditor><generator>Blogger</generator><openSearch:totalResults>64</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/dev-logger" /><feedburner:info uri="dev-logger" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-5286603484073646452</guid><pubDate>Tue, 25 Sep 2012 00:10:00 +0000</pubDate><atom:updated>2012-09-24T17:27:17.069-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">functional programming</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><title>Is the Future Functional? by Rob Harrop</title><description>&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Here are my notes on Rob Harrop's &lt;a href="http://skillsmatter.com/podcast/home/qcon-future-functional/"&gt;presentation about functional programming&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Functional is important because&lt;/span&gt;&lt;/h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;b&gt;1) Simplicity&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;it's declarative&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;you write what you want to achieve, rather than give instructions how to achieve it&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;express solutions, not worry about individual steps&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;b&gt;2) Agility&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;functional fits well with Agile methodology&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;testing is much easier (because of purity, no side-effects)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;b&gt;3) Contentment&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;self-content while you are working&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;b&gt;4) Concurrency&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;e.g. parallelization&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;often the reason why people switch to functional&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Imperative vs functional languages&lt;/span&gt;&lt;/h4&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Functional:&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;function application (calculations to data), not state change&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;immutable state (makes testing easier)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Imperative:&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;focus on decisions (instructions), and state change&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;mutable state&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Functional:&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;recursion not looping&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;descriptions (of solutions), not statements&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Functional features&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;higher-order functions&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;pure functions (same args in always lead to same results)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;recursion&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;type systems (Haskell: strong typing; Erlang, LISP: loosely typed)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;strict/lazy evaluation&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;b&gt;DDD&lt;/b&gt;: primary focus should be on the domain and domain logic&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;DDD concepts&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;ubiquitous language&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;strategic design (identify which bits are harder to model and put time on it)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;models&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;context&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Domain-driven with imperative programming leads to anxiety. Always wondering if you got your model right, because there are a myriad of ways to implement a solution.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Functional DDD&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;core concepts still apply&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;everything is just a function or data structure&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Why is functional better?&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;fewer concepts (no factories, no patterns)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;easier concepts&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;lower model overhead&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span class="Apple-style-span" style="background-color: white;"&gt;Modelling&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;UML doesn't really work for functional&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;fortunately, we all know how to model in functional languages&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/la5TBsPXq3A" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/la5TBsPXq3A/is-future-functional-by-rob-harrop.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2012/09/is-future-functional-by-rob-harrop.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-4432127596123419602</guid><pubDate>Thu, 13 Sep 2012 15:10:00 +0000</pubDate><atom:updated>2013-02-22T08:42:49.875-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Unix</category><category domain="http://www.blogger.com/atom/ns#">tips</category><category domain="http://www.blogger.com/atom/ns#">Ubuntu</category><title>Transferring large files: easy and free!</title><description>I needed to transfer a 4GB file the other day. Unfortunately, there is no easy and free way to do it. So I went the tech way.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
How to&lt;/h4&gt;
Upload the file to my_server (e.g. your server slice) via scp:&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;scp my_large_file my_server:.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In case your connection breaks up, you can resume the upload like this:&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;rsync --partial --progress my_large_file my_server:.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Log to your slice and move the file to a directory of its own:&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ssh my_server&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mkdir pub_data&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mv my_large_file pub_data/&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Start a simple HTTP server on the port of your choice (in this case 8080), by running:&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;python -mSimpleHTTPServer 8080 &amp;amp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That's it! Your file is now available for download at:&lt;br /&gt;
http://my_server_hostname:8080/my_large_file&lt;br /&gt;
&lt;br /&gt;
If you want to have that HTTP server process running even after logging out, find out its PID by running the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;jobs&lt;/span&gt; command, and then you can disown that process from the shell like so (assuming the PID was 1):&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;disown %1&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Advantages&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;no need to go through the hassle of installing a FTP server on your own machine.&lt;/li&gt;
&lt;li&gt;don't care about leaving your machine turned on because you don't know exactly when the other party will be fetching the file.&lt;/li&gt;
&lt;li&gt;the other party is not slowed down by your ISP's upload limits while trying to fetch the file from you.&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/T23Ui_O9xIQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/T23Ui_O9xIQ/transferring-large-files-easy-and-free.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2012/09/transferring-large-files-easy-and-free.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-8057709480086302112</guid><pubDate>Tue, 29 May 2012 21:31:00 +0000</pubDate><atom:updated>2012-05-29T14:33:18.356-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Unix</category><title>How to remove every n-th line from a file</title><description>A bit of googling made me read &lt;a href="http://duanesbrain.blogspot.ca/2006/03/unix-cat-every-nth-third-fourth-fifth.html"&gt;this article&lt;/a&gt;, which was about sampling a file. What I really wanted was to remove every fifth line from a file. &lt;br /&gt;
&lt;br /&gt;
Here is the input file:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;1&lt;br /&gt;
00:00:06,244 --&gt; 00:00:09,004&lt;br /&gt;
The public has a very romantic idea of what wine's about.&lt;br /&gt;
Le public a une idée très romantique du vin. &lt;br /&gt;
&lt;br /&gt;
2&lt;br /&gt;
00:00:09,984 --&gt; 00:00:14,373&lt;br /&gt;
They think it's some little guy, like me, working in the cellar,&lt;br /&gt;
On pense que c'est un petit producteur, comme moi, qui travaille à la cave,&lt;br /&gt;
&lt;br /&gt;
3&lt;br /&gt;
00:00:14,473 --&gt; 00:00:16,741&lt;br /&gt;
working in the vineyard, bringing the grapes in.&lt;br /&gt;
qui travaille dans le vignoble, qui vendange ses raisins.&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
And I wanted to have that kind of output:&lt;br /&gt;
&lt;div class="codeSnippet"&gt;1&lt;br /&gt;
00:00:06,244 --&gt; 00:00:09,004&lt;br /&gt;
Le public a une idée très romantique du vin. &lt;br /&gt;
&lt;br /&gt;
2&lt;br /&gt;
00:00:09,984 --&gt; 00:00:14,373&lt;br /&gt;
On pense que c'est un petit producteur, comme moi, qui travaille à la cave,&lt;br /&gt;
&lt;br /&gt;
3&lt;br /&gt;
00:00:14,473 --&gt; 00:00:16,741&lt;br /&gt;
qui travaille dans le vignoble, qui vendange ses raisins.&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
So this made the trick:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;awk '{if ((count++ +2)%5!=0) print $0;}' input_file.srt &gt; output_file.srt&lt;br /&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/lggRhAyf0DU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/lggRhAyf0DU/how-to-remove-every-n-th-line-from-file.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2012/05/how-to-remove-every-n-th-line-from-file.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-8664649957550242289</guid><pubDate>Fri, 30 Mar 2012 23:38:00 +0000</pubDate><atom:updated>2012-03-30T16:56:24.718-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">books</category><title>JavaScript: The Good Parts by Douglas Crockford</title><description>I have really enjoyed reading &lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742"&gt;JavaScript: The Good parts&lt;/a&gt;. It has been recommended to me by many friends, and I'm certainly not disappointed. Douglas Crockford did an excellent job.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/--lGp3s_8ZrM/T3ZDrHHybgI/AAAAAAAAAVs/RMx2RAOWUsE/s1600/crockford-cover.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/--lGp3s_8ZrM/T3ZDrHHybgI/AAAAAAAAAVs/RMx2RAOWUsE/s320/crockford-cover.png" width="249" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
The book is highly opinionated, and that's a good thing, given that the author is seen as a prolific and talented Javascript expert by his peers. Here is an excerpt that gives you an idea of the book's tone:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
The best thing about JavaScript is its implementation of functions. It got almost everything right. But, as you should expect with JavaScript, it didn't get everything right.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;h3&gt;



Things to remember&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The prototype link is used only in retrieval. If you set a new property on an object (not on the prototype), it sets it on the receiver only.&lt;/li&gt;
&lt;li&gt;The &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;hasOwnProperty&lt;/span&gt; method does not look at the prototype chain. It looks in the receiver only.&lt;/li&gt;
&lt;li&gt;Objects are passed around by reference. They are never copied.&lt;/li&gt;
&lt;li&gt;It is important to understand that the inner function has access to the actual variables of the outer functions and not copies.&lt;/li&gt;
&lt;li&gt;Objects produced from object literals are linked to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Object.prototype&lt;/span&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Function objects are linked to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Function.prototype&lt;/span&gt; (which is itself linked to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Object.prototype&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;JavaScript does not have block scope. JavaScript does have function scope.&lt;/li&gt;
&lt;li&gt;The general pattern of a module is a function that defines private variables and functions; creates privileged functions which, through closure, will have access to the private variables and functions; and that returns the privileged functions or stores them in an accessible place.&lt;/li&gt;
&lt;li&gt;If all of the state of an object is private, then the object is tamper-proof. Properties of the object can be replaced or deleted, but the integrity of the object is not compromised. If we create an object in the functional style, and if all of the methods of the object make no use of this or that, then the object is durable. A durable object is simply a collection of functions that act as capabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: 19px; font-weight: bold;"&gt;Advice&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;It is best to declare all of the variables used in a function at the top of the function body.&lt;/li&gt;
&lt;li&gt;One way to minimize the use of global variables is to create a single global variable for your application:&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;var MYAPP = {};&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h3&gt;


&lt;/h3&gt;
&lt;h3&gt;


Is this book for you?&lt;/h3&gt;
&lt;br /&gt;
If you are wondering if you should read that book, you could test yourself. If you fully understand the code snippet below, you can skip it. If not, then you might want to invest in some quality reading. It's an excellent book to beef up your Javascript understanding.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&lt;span style="color: cyan;"&gt;&lt;b&gt;Function&lt;/b&gt;&lt;/span&gt;.method(&lt;span style="color: #ff40ff;"&gt;'bind'&lt;/span&gt;, &lt;span style="color: cyan;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt;&amp;nbsp;(that)&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&amp;nbsp;method = &lt;span style="color: cyan;"&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;slice = &lt;span style="color: #87ffaf;"&gt;Array&lt;/span&gt;.prototype.slice,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;args = slice.apply(&lt;span style="color: cyan;"&gt;&lt;b&gt;arguments&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: cyan;"&gt;&lt;b&gt;[&lt;/b&gt;&lt;/span&gt;1&lt;span style="color: cyan;"&gt;&lt;b&gt;]&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt;&amp;nbsp;(&amp;nbsp;&amp;nbsp;)&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;return&lt;/span&gt;&amp;nbsp;method.apply(that,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;args.concat(slice.apply(&lt;span style="color: cyan;"&gt;&lt;b&gt;arguments&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: cyan;"&gt;&lt;b&gt;[&lt;/b&gt;&lt;/span&gt;0&lt;span style="color: cyan;"&gt;&lt;b&gt;]&lt;/b&gt;&lt;/span&gt;)));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color: cyan;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;
&lt;span style="color: cyan;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&amp;nbsp;x = &lt;span style="color: cyan;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt;&amp;nbsp;(&amp;nbsp;&amp;nbsp;)&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;.value;&lt;br /&gt;
&lt;span style="color: cyan;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;.bind(&lt;span style="color: cyan;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;value: 666&lt;span style="color: cyan;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;
&lt;span style="color: yellow;"&gt;alert&lt;/span&gt;(x(&amp;nbsp;&amp;nbsp;)); &lt;span style="color: cyan;"&gt;// 666&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/7TsY9JNU5Os" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/7TsY9JNU5Os/javascript-good-parts-by-douglas.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/--lGp3s_8ZrM/T3ZDrHHybgI/AAAAAAAAAVs/RMx2RAOWUsE/s72-c/crockford-cover.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2012/03/javascript-good-parts-by-douglas.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-3499231977829484105</guid><pubDate>Thu, 02 Feb 2012 02:10:00 +0000</pubDate><atom:updated>2012-02-01T18:22:28.562-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><category domain="http://www.blogger.com/atom/ns#">Ruby1.9</category><title>An Introduction to Procs, by Peter Cooper</title><description>I have just watched the &lt;a href="http://www.youtube.com/watch?v=VBC-G6hahWA"&gt;27-min introduction on Procs by Peter Cooper&lt;/a&gt;, which is really a short section of his &lt;a href="http://www.rubyreloaded.com/"&gt;RubyReloaded&lt;/a&gt; course.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://www.youtube.com/watch?v=VBC-G6hahWA"&gt;&lt;img border="0" height="221" src="http://1.bp.blogspot.com/-m-IWqPlsM7M/Tynv-cLQefI/AAAAAAAAAVk/DpTWalvxKR8/s400/pc+proc.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Here are my notes:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;blocs are essentially nameless functions&lt;/li&gt;
&lt;li&gt;the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;block_given?&lt;/span&gt; method can be used to find out if a block was passed to the current scope&lt;/li&gt;
&lt;li&gt;blocks are anonymous functions which can be passed around and called at will&lt;/li&gt;
&lt;li&gt;one can only pass a single block to a method, but one can pass multiple procs around (as arguments of a method)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc.new&lt;/span&gt; will create a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc&lt;/span&gt; object if there was a block passed in the current context (otherwise it will raise an error)&lt;/li&gt;
&lt;li&gt;In Ruby 1.9, there are 4 ways to call (or run) proc objects:&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;my_proc = &lt;span style="color: #87ffaf;"&gt;Proc&lt;/span&gt;.new &lt;span style="color: yellow;"&gt;do&lt;/span&gt;&amp;nbsp;|&lt;span style="color: cyan;"&gt;&lt;b&gt;e&lt;/b&gt;&lt;/span&gt;|&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;puts &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;this is &lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;#{&lt;/span&gt;e&lt;span style="color: #ffd7d7;"&gt;}&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
my_proc.call(&lt;span style="color: #ff40ff;"&gt;2&lt;/span&gt;)&lt;br /&gt;
my_proc.(&lt;span style="color: #ff40ff;"&gt;2&lt;/span&gt;)&lt;br /&gt;
my_proc[&lt;span style="color: #ff40ff;"&gt;2&lt;/span&gt;]&lt;br /&gt;
my_proc === &lt;span style="color: #ff40ff;"&gt;2&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;lambda&lt;/span&gt; is a proc object which respects argument arity, much like an anonymous method&lt;/li&gt;
&lt;li&gt;in 1.8, "proc" (surprisingly) created a lambda (and not a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc&lt;/span&gt; object)&lt;/li&gt;
&lt;li&gt;in 1.9, "proc" is the same as doing &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc.new&lt;/span&gt; (as we would expect)&lt;/li&gt;
&lt;li&gt;a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;return&lt;/span&gt; in a proc will try to return from the context where the proc was defined (and not from where it is executed)&lt;/li&gt;
&lt;li&gt;in a closure, ruby keeps &lt;i&gt;references&lt;/i&gt; to variables. You can thus modify a variable's value inside a proc even after the proc was defined. Thus this code will output "Marc":&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;run_proc&lt;/b&gt;&lt;/span&gt;(p)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;p.call&lt;br /&gt;
&lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
name = &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Fred&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;br /&gt;my_proc = &lt;span style="color: yellow;"&gt;proc&lt;/span&gt;&amp;nbsp;{ puts name }&lt;br /&gt;name = &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Marc&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;br /&gt;run_proc my_proc&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/jM3wd05f2Eg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/jM3wd05f2Eg/introduction-to-procs-by-peter-cooper.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-m-IWqPlsM7M/Tynv-cLQefI/AAAAAAAAAVk/DpTWalvxKR8/s72-c/pc+proc.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2012/02/introduction-to-procs-by-peter-cooper.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-7774778494448925424</guid><pubDate>Wed, 11 Jan 2012 03:20:00 +0000</pubDate><atom:updated>2012-01-10T19:33:40.232-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">architecture</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><title>Architecture the Lost Years, by Robert Martin</title><description>I watched a &lt;a href="http://confreaks.net/videos/759-rubymidwest2011-keynote-architecture-the-lost-years"&gt;keynote from Robert Martin during the Ruby Midwest 2011 conference&lt;/a&gt;. It's always fun to watch veterans from the field.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://confreaks.net/videos/759-rubymidwest2011-keynote-architecture-the-lost-years"&gt;&lt;img border="0" height="209" src="http://3.bp.blogspot.com/-Y2EyU0L4HuA/Twymf2QI1QI/AAAAAAAAAVU/LD0qs2C1c4w/s400/uncle+bob.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Here are some thoughts:&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;

Decoupling&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;the whole talk is about decoupling &lt;/li&gt;
&lt;li&gt;the web is just a "delivery mechanism"&lt;/li&gt;
&lt;li&gt;
Ivar Jacobson's &lt;a href="http://www.amazon.ca/Object-Oriented-Software-Engineering-Approach/dp/0201544350"&gt;use case driven approach&lt;/a&gt;:&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;make the intent of your system obvious &lt;/li&gt;
&lt;li&gt;architecture: boundary, interactor (app specific), entity (app agnostic)&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://www.amazon.ca/Object-Oriented-Software-Engineering-Approach/dp/0201544350" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-EM7GhPXUbps/Tw0AAiEpQ8I/AAAAAAAAAVc/WBlsLF9Eorc/s200/ivar_jacobson.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;we should keep in mind that:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;the delivery mechanism (e.g. the web) is "just a detail"&lt;/li&gt;
&lt;li&gt;the database is "just a detail"&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Architecture&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;art of architecture: drawing lines&lt;/li&gt;
&lt;li&gt;architecture is about:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;drawing lines&lt;/li&gt;
&lt;li&gt;when you have a line crossing another, it's a dependency&lt;/li&gt;
&lt;li&gt;making sure all dependency lines goes into the same direction (when crossing a line) &lt;/li&gt;
&lt;li&gt;once you have that you have a gem/plugin &lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;a good architecture allows major decisions to be deferred&lt;/li&gt;
&lt;li&gt;if the first thing you type is "rails new_app", you've lost it. Rather, you must think about your entities, interactors and boundaries&lt;/li&gt;
&lt;li&gt;a good architecture maximizes the number of decisions NOT made&lt;/li&gt;
&lt;li&gt;in software engineering, at the end of the 80s, we were on the verge to understand that software architecture needed a use case-driven approach. But then the web got us away from it. And now we seem to be in the process of remembering it.&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/1uHPWFimTXw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/1uHPWFimTXw/architecture-lost-years-by-robert.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-Y2EyU0L4HuA/Twymf2QI1QI/AAAAAAAAAVU/LD0qs2C1c4w/s72-c/uncle+bob.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2012/01/architecture-lost-years-by-robert.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-5688190841739272182</guid><pubDate>Sun, 18 Dec 2011 23:24:00 +0000</pubDate><atom:updated>2011-12-18T20:49:32.221-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><category domain="http://www.blogger.com/atom/ns#">Ruby metaprogramming</category><title>Ruby Object Model and Metaprogramming screencasts by Dave Thomas</title><description>I bought 6 &lt;a href="http://pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming"&gt;screencast episodes of Ruby metaprogramming&lt;/a&gt; about 3 years ago and only recently have I watched them all. And I must say: it was quite worth it! Just a reminder that it's never too late :) See below for my notes (which have been approved by Dave Thomas himself).&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming" imageanchor="1"&gt;&lt;img border="1" height="299" src="http://1.bp.blogspot.com/-gYmkUznSVIM/Tu5v_mjVDkI/AAAAAAAAAVM/TvBVrr1wguY/s400/DaveThomas.jpg" style="margin: 1px;" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Episode 1 - Objects and Classes&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Think in terms of object-oriented programming instead of class-oriented programming&lt;/li&gt;
&lt;li&gt;2 ways to change self:&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;by a method call with an explicit receiver&lt;/li&gt;
&lt;li&gt;by a class or module definition&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;a class does not have a name until you assign it to a constant&lt;/li&gt;
&lt;li&gt;classes are first-class objects&lt;/li&gt;
&lt;li&gt;class methods don't exist: they are actually singleton methods on class objects&lt;/li&gt;
&lt;li&gt;method calling always works the same way. The ruby interpreter:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;identifies the class of the receiver&amp;nbsp;&lt;/li&gt;
&lt;li&gt;looks up the method in that receiver's class&lt;/li&gt;
&lt;li&gt;if it does not find it, it goes up the hierarchy, and looks up the method in the parent of that class&lt;/li&gt;
&lt;li&gt;retries the last step until it finds it&amp;nbsp; &lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Episode II - Sharing Behavior&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;  Object#clone() copies the singleton method too; Object#dup() does not &lt;/li&gt;
&lt;li&gt;with a prototype, you can clone both the behavior and the state of an object (which is not the case with class-based inheritance)&lt;/li&gt;
&lt;li&gt;one can subclass from any expression, e.g. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class A &amp;lt; (rand &amp;gt; 0.5 ? B : C)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;do something in the singleton class like so: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class &amp;lt;&amp;lt; self ; # ... ; end&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;modules have 3 distinct usages:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;namespace&lt;/li&gt;
&lt;li&gt;to create module methods&lt;/li&gt;
&lt;li&gt; to create instance methods&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;module methods can still be modified even if they have been included in a class, by reopening the module&lt;/li&gt;
&lt;li&gt;a method of an included module will come before a method defined in a superclass, during Ruby's method lookup&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;extend(module_name)&lt;/span&gt; actually opens the receiver's singleton class and sticks the content of&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;module_name&lt;/span&gt; in it&lt;/li&gt;
&lt;li&gt;reason because &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Person &amp;lt; ActiveRecord::Base&lt;/span&gt; is conceptually wrong: the intention is not to build a hierarchy (a "is a" relationship), but rather to share behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Episode III - Dynamic Code&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;several ways to create blocks. Worth mentioning:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;lambda cares about arity (just like a method), proc does not&amp;nbsp;&lt;/li&gt;
&lt;li&gt;a "return" inside a proc exits surrounding context&lt;/li&gt;
&lt;li&gt;a "return" in a lambda exits the lambda&lt;/li&gt;
&lt;li&gt;a "return" inside a do/end block will exist the surrounding context&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;lambda&lt;/span&gt; : like an anonomymous method&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Proc.new&lt;/span&gt; : like inline code&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;a Kernel method is available everywhere in our program&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt; takes a string and evaluates it as ruby code&lt;/li&gt;
&lt;li&gt;a binding encapsulates:&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;self,&amp;nbsp;&lt;/li&gt;
&lt;li&gt;local variables (including method params)&lt;/li&gt;
&lt;li&gt;any associated block&lt;/li&gt;
&lt;li&gt;return stack&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;a proc object always has an associated binding&lt;/li&gt;
&lt;li&gt;nothing prevents you from defining a method within a method&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;define_method()&lt;/span&gt; is only available in modules and classes&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Episode IV - instance_eval() and class_eval()&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt; instance_eval() can be called on any object&lt;/li&gt;
&lt;li&gt;class_eval() is an alias to module_eval&lt;/li&gt;
&lt;li&gt;class_eval() can only be called on classes and modules&lt;/li&gt;
&lt;li&gt;a method definition in class_eval() evaluates in the receiver's class (thus creating instance methods)&lt;/li&gt;
&lt;li&gt;a method definition in instance_eval() evaluates in the receiver's singleton class (thus creating class methods)&lt;/li&gt;
&lt;li&gt;"self" in a block of class_eval() or instance_eval() is set to the receiver's&lt;/li&gt;
&lt;li&gt;include() is a private method&lt;/li&gt;
&lt;li&gt;you can change the "self" of a block with instance_eval(&amp;amp;block), e.g.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&lt;span style="color: #5fd7ff;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #87ffaf;"&gt;Robot&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;move&lt;/b&gt;&lt;/span&gt;(&amp;amp;block)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;instance_eval&lt;/span&gt;( &amp;amp;block )&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;up&lt;/b&gt;&lt;/span&gt;;&amp;nbsp;&amp;nbsp;puts &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;u&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;; &lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;down&lt;/b&gt;&lt;/span&gt;; puts &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;d&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;; &lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
robot = &lt;span style="color: #87ffaf;"&gt;Robot&lt;/span&gt;.new&lt;br /&gt;
robot.move &lt;span style="color: yellow;"&gt;do&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;up&amp;nbsp;&amp;nbsp; &lt;span style="color: cyan;"&gt;# no need for robot.up()&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;down &lt;span style="color: cyan;"&gt;# no need for robot.down()&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Episode V - Nine examples&lt;/b&gt; &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;memoization: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;@memory[skus] ||= expensive_calculation()&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;interesting examples making use of several metaprogramming techniques seen in previous episodes. If there's one episode to watch, make it that one!&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Episode VI - Some hook methods&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Struct.new returns a subclass of Struct&lt;/li&gt;
&lt;li&gt;method-related hooks:&lt;/li&gt;
&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
&lt;li&gt;method_missing&lt;/li&gt;
&lt;li&gt;method_added&lt;/li&gt;
&lt;li&gt;singleton_method_added&lt;/li&gt;
&lt;li&gt;method_removed&lt;/li&gt;
&lt;li&gt;singleton_method_removed&lt;/li&gt;
&lt;li&gt;method_undefined&lt;/li&gt;
&lt;li&gt;singleton_method_undefined&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Class and Module hooks:&lt;/li&gt;
&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
&lt;li&gt;inherited&lt;/li&gt;
&lt;li&gt;append_features&lt;/li&gt;
&lt;li&gt;included&lt;/li&gt;
&lt;li&gt;extend_object&lt;/li&gt;
&lt;li&gt;extended&lt;/li&gt;
&lt;li&gt;initialize_copy&lt;/li&gt;
&lt;li&gt;const_missing&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Marshalling hooks:&lt;/li&gt;
&lt;ul&gt;
&lt;li style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;marshal_dump&lt;/li&gt;
&lt;li style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;marshal_load&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Coercion hooks:&lt;/li&gt;
&lt;ul&gt;
&lt;li style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;coerce&lt;/li&gt;
&lt;li style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;induced_from&lt;/li&gt;
&lt;li&gt;to_xxx , e.g. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;to_s&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;to_proc&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;advice: don't forget to call the original method when writin code in the hook method to preserve behavior&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/iOXuch8Q2Lk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/iOXuch8Q2Lk/ruby-object-model-and-metaprogramming.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-gYmkUznSVIM/Tu5v_mjVDkI/AAAAAAAAAVM/TvBVrr1wguY/s72-c/DaveThomas.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2011/12/ruby-object-model-and-metaprogramming.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-2207713332428794210</guid><pubDate>Tue, 06 Dec 2011 04:45:00 +0000</pubDate><atom:updated>2011-12-06T08:08:35.713-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">OSX</category><category domain="http://www.blogger.com/atom/ns#">Rails</category><title>Ssh credentials not forwarded when using Capistrano on Mac OS X Snow Leopard</title><description>I'm running Snow Leopard and it seems like a fresh Capistrano install did not forward my ssh credentials when I was deploying my Rails 3 app on a remote server, having my git repo on &lt;a href="http://beanstalkapp.com/"&gt;beanstalk&lt;/a&gt; (similar to the popular &lt;a href="http://github.com/"&gt;github&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
After a lot of googling, I &lt;a href="http://bambinos.tumblr.com/post/229845419/solving-the-problem-of-non-working-key-forwarding-with"&gt;understood the problem&lt;/a&gt; and went on to fix it. For me, it was a matter of adding my private ssh key to my ssh-agent, like so:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
ssh-add ~/.ssh/id_rsa&lt;/div&gt;
&lt;br /&gt;
Then, when running: &lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
ssh-add -L&lt;/div&gt;
&lt;br /&gt;
I could finally see my public ssh key listed (before, no keys were shown). I re-fired a "cap deploy", and it finally worked. With 3 hours of my life down the drain.&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/-Z_6bYJooR0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/-Z_6bYJooR0/ssh-credentials-not-forwarded-when.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>2</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2011/12/ssh-credentials-not-forwarded-when.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-6845397499819171925</guid><pubDate>Tue, 22 Nov 2011 22:32:00 +0000</pubDate><atom:updated>2011-11-23T09:43:34.094-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby quiz (intermediate)</category><title>Ruby quiz (intermediate) #6</title><description>&lt;b&gt;Question&lt;/b&gt;: What would be the output of this code snippet?&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;1 &lt;/span&gt;&lt;span style="color: #5fd7ff;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #87ffaf;"&gt;A&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;attr_accessor&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;:var&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;3 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;method&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;4 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var = &lt;span style="color: #ff40ff;"&gt;45&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;5 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;6 &lt;/span&gt;&lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;7 &lt;/span&gt;&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;8 &lt;/span&gt;a = &lt;span style="color: #87ffaf;"&gt;A&lt;/span&gt;.new&lt;br /&gt;
&lt;span style="color: yellow;"&gt;&amp;nbsp;9 &lt;/span&gt;a.method&lt;br /&gt;
&lt;span style="color: yellow;"&gt;10&amp;nbsp;&lt;/span&gt;puts a.var&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Solution&lt;/b&gt;: The output is "nil". Here is the answer, taken from &lt;a href="http://pragprog.com/book/ruby/programming-ruby"&gt;Programming Ruby 2nd edition&lt;/a&gt;&amp;nbsp;(p. 86):&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
[W]ritable attributes have a hidden gotcha. Normally, methods within a class can invoke other methods in the same class and its superclasses in functional form (that is, with an implicit receiver of self). However, this doesn’t work with attribute writers. Ruby sees the assignment and decides that the name on the left must be a local variable, not a method call to an attribute writer.&lt;/blockquote&gt;
As such, the attribute &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;:var&lt;/span&gt; has never been assigned any value, and thus at line 10, its value is still "nil". More appropriately,&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;self.var = 45&lt;/span&gt; would have assigned the value &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;45&lt;/span&gt; to the attribute&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;:var&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/G7UlZqv2X1A" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/G7UlZqv2X1A/ruby-quiz-intermediate-6.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2011/11/ruby-quiz-intermediate-6.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-5972055664983548500</guid><pubDate>Sun, 20 Nov 2011 14:17:00 +0000</pubDate><atom:updated>2012-02-01T18:27:33.073-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><category domain="http://www.blogger.com/atom/ns#">Ruby1.9</category><title>Ruby 1.9 Walkthrough by Peter Cooper</title><description>I have been away from hacking some Ruby for about a year by now, and I wanted to get up to speed with Ruby 1.9.3, so I bought&amp;nbsp;&lt;a href="http://www.rubyinside.com/19walkthrough/"&gt;Peter Cooper's Ruby 1.9 Walkthrough&lt;/a&gt;. No doubt: my $24 was excellent value for my money.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://www.rubyinside.com/19walkthrough/" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-XH75DP6gWkg/TsgeUlhy7HI/AAAAAAAAAVE/QIVIIbXrnyg/s1600/Ruby+1.9+Walkthrough.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
That's a 3-hour session where he talks about what's new in Ruby 1.9.2 and 1.9.3. &amp;nbsp;I certainly recommend it because it's fun, pedagogical, and rather comprehensive.&lt;br /&gt;
&lt;br /&gt;
Here are my notes (which have been approved by Peter Cooper himself):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Strings&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Parse lines in a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String&lt;/span&gt; object with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#each_line&lt;/span&gt; or &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#lines&lt;/span&gt;, instead of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#each&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#ord&lt;/span&gt; returns the UTF-8 index&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"x".ord&lt;/span&gt; is the new way of doing &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;?x&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;?a&amp;nbsp;== "a"&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; (and no more "97")&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"A".ord == 65,&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"ABC".ord == 65&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#codepoints&lt;/span&gt; to get an enumerator of each codepoint (UTF-8 index)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;gt; &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Aab&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;.codepoints.each {|&lt;span style="color: cyan;"&gt;&lt;b&gt;x&lt;/b&gt;&lt;/span&gt;|&amp;nbsp;print &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;#{&lt;/span&gt;x&lt;span style="color: #ffd7d7;"&gt;}&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: #ff40ff;"&gt;65&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;97&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;98&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Aab&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#clear&lt;/span&gt; clears to an empty string in place&lt;/li&gt;
&lt;li&gt;String are now in terms of characters (UTF-8 by default) rather than bytes&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#length&lt;/span&gt; now returns length in chars, not bytes&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#[]&lt;/span&gt; now returns entire characters, not individual bytes&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#encoding&lt;/span&gt; returns the relevant &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Encoding&lt;/span&gt; object for the string&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Encoding.list.length&lt;/span&gt; = 95 encodings&lt;/li&gt;
&lt;li&gt;tip #1:&amp;nbsp;explicitly declare encodings on any IO objects you're opening&lt;/li&gt;
&lt;li&gt;tip #2: add the magic comment on top of all source files (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# encoding: utf-8&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Hashes&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;new hash syntax: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{name: "value"}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash&lt;/span&gt; instance is now an ordered &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#select&lt;/span&gt; now returns a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash&lt;/span&gt; instead of an &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#select!&lt;/span&gt; is an in-place version of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#select&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;new methods: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#default_proc&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#default_proc=&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#flatten&lt;/span&gt; turns the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash&lt;/span&gt; into an interleaved &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;new methods: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#assoc&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#rassoc&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash#keep_if&lt;/span&gt; amends a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Hash&lt;/span&gt; in place&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Arrays&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#to_s&lt;/span&gt; no longer joins, but returns an #inspect-style representation&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#choice&lt;/span&gt; goes, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#sample&lt;/span&gt; arrives (and takes an optional quantity arg)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#shuffle&lt;/span&gt; is still around&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#uniq&lt;/span&gt;, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#uniq!&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#product&lt;/span&gt; now take blocks&lt;/li&gt;
&lt;li&gt;not new but useful: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Array#inject&lt;/span&gt; can take a symbol representing a method to run each time, e.g. &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;inject(:+)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Procs and Lambdas&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;proc {}&lt;/span&gt; now creates a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc&lt;/span&gt;, not a lambda like in 1.8&lt;/li&gt;
&lt;li&gt;check if &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc&lt;/span&gt; objects are lambdas with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#lambda?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;recap: lambdas enforce arity (argument count), regular procs do not&lt;/li&gt;
&lt;li&gt;"stabby" lambda syntax: -&amp;gt;x{x * 2 } or -&amp;gt;(x,y,z){x * y * z}&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc#[]&lt;/span&gt; still works for calling a proc/lambda (as does #call)&lt;/li&gt;
&lt;li&gt;recap: Ruby 1.8 lambdas didn't enforce arity when no params were listed, and it's been fixed in 1.9&lt;/li&gt;
&lt;li&gt;recap: Ruby 1.8 lambdas with 1 param only gave a warning when called with many args, and it's now fixed in 1.9&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;.()&lt;/span&gt; calls the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#call&lt;/span&gt; method on proc/lambda, but also on other types of object&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&amp;gt; a = {}; &lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;a.&lt;span style="color: cyan;"&gt;&lt;b&gt;call&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: #ff40ff;"&gt;20&lt;/span&gt;; &lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;; a.()&lt;br /&gt;
&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;20&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc#===&lt;/span&gt; will call the proc/lambda (useful in case statements in a "when" block)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&amp;nbsp;&amp;gt; -&amp;gt;x{ x.odd? }&amp;nbsp;=== &lt;span style="color: #ff40ff;"&gt;3&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;true&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc#curry&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; takes a multiple arg proc and turns it into a chain of single arg procs&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&amp;gt;&lt;span style="font-family: monospace;"&gt;
&amp;nbsp;&amp;gt; -&amp;gt;(a,b,c){ a + b + c }.curry[&lt;span style="color: #ff40ff;"&gt;1&lt;/span&gt;][&lt;span style="color: #ff40ff;"&gt;2&lt;/span&gt;][&lt;span style="color: #ff40ff;"&gt;3&lt;/span&gt;]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;6&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc#source_location&lt;/span&gt; returns &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[filename, line_number]&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Blocks&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Block parameters are now always local to their block&lt;/li&gt;
&lt;li&gt;non block parameters are not seen in a different scope when in a block&lt;/li&gt;
&lt;li&gt;in a block parameter list, you can list block-local variables, after a semi-colon&lt;/li&gt;
&lt;li&gt;you can now pass a block when calling a proc:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;gt; &lt;span style="color: yellow;"&gt;proc&lt;/span&gt;&amp;nbsp;{|&amp;amp;&lt;span style="color: cyan;"&gt;&lt;b&gt;b&lt;/b&gt;&lt;/span&gt;|&amp;nbsp;b.call(&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;hello&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;) }.call {|&lt;span style="color: cyan;"&gt;&lt;b&gt;c&lt;/b&gt;&lt;/span&gt;|&amp;nbsp;puts c}&lt;br /&gt;hello&lt;br /&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;nil&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Enumerator&lt;/span&gt; was back-ported to Ruby 1.8.7&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Enumerator#with_index&lt;/span&gt; accepts an optional starting index&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Enumerator#with_object&lt;/span&gt; accepts an object,&amp;nbsp;e.g. &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1.2.3].each.with_object({}) {|i,a| a[i] = i}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Enumerator#peek&lt;/span&gt; checks out next item w/o advancing pointer&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Regular Expressions&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"abc123" =~ /[[:digit]]/&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"a++"&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; returns&amp;nbsp;&lt;/span&gt;1 or more "a" but 'possessive' (no backtracking allowed by parser)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(?= … )&lt;/span&gt; is a zero-width positive lookahead&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(?&amp;lt;= … )&lt;/span&gt; is a zero-width positive lookbehind&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(?!&amp;nbsp;… )&lt;/span&gt;&amp;nbsp;are zero-width negative lookahead&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(?&amp;lt;!&amp;nbsp;… )&lt;/span&gt;&amp;nbsp;is a zero-width negative lookbehind&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(?&amp;lt;name&amp;gt;pattern)&lt;/span&gt; is a "named match" or "named group" called "name"&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MatchData#[]&lt;/span&gt; lets you use matched names using symbols, e.g. &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;md[:name]&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(?&amp;lt;name&amp;gt;…){0}&lt;/span&gt; doesn't match immediately but stores regex for later&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;\g&amp;lt;name&amp;gt; &lt;/span&gt;makes use of the named match "name" at the current point&lt;/li&gt;
&lt;li&gt;Unicode properties: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;\p{property name}&lt;/span&gt; (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;\P{property name}&lt;/span&gt; for opposite)&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Threads&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Threads are real system-level threads&lt;/li&gt;
&lt;li&gt;GIL (Global Interpreter Lock) still applies&lt;/li&gt;
&lt;li&gt;enforce that only one thread can run at any one time in the Ruby VM&lt;/li&gt;
&lt;li&gt;IO is async thread (another thread can run while IO is occurring)&lt;/li&gt;
&lt;li&gt;C extensions have the option to "release" the GIL&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Thread#set_trace_func&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Thread#add_trace_func&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Fibers&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;lighter way of doing concurrency&lt;/li&gt;
&lt;li&gt;fiber is a subroutine with multiple entry points&lt;/li&gt;
&lt;li&gt;Ruby VM uses fibers to implement enumerators internally&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Fiber#new&lt;/span&gt; to create a new &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Fiber&lt;/span&gt; object&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Fiber#resume&lt;/span&gt; will resume execution of the fiber&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Fiber.yield&lt;/span&gt; yields control (and sometimes data) back to the caller&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Time&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time#parse&lt;/span&gt; was using the American format; it'snow using the British format, e.g. &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time.parse("30/12/2001")&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;We now have: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time#monday?&lt;/span&gt;, &amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time#tuesday?&lt;/span&gt; , etc&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time.now.usec&lt;/span&gt; gives the microseconds&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(Time.now == Time.now)&lt;/span&gt; will return false&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time.now.subsec&lt;/span&gt; returns a fraction of 1 000 000 usec&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;New in the Standard Library&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;JSON support: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#to_json&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;JSON.load(js)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;j and jj&lt;/li&gt;
&lt;li&gt;Syck and Psych&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MiniTest&lt;/span&gt; runs test methods in a random order to test their fragility&lt;/li&gt;
&lt;li&gt;Need to add &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"minitest/autorun"&lt;/span&gt; to make &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MiniTest&lt;/span&gt; tests run automatically&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;assert_not_[something]&lt;/span&gt; becomes &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;refute_[something]&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;must_equal()&lt;/span&gt; becomes &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;wont_equal() &lt;/span&gt;in the negative&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;FasterCSV&lt;/span&gt; becomes &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CSV&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Foreign Function Interface&lt;/span&gt; library&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Fiddle&lt;/span&gt; library : a nice abstraction to make using FFI easier&lt;/li&gt;
&lt;li&gt;rake is now included&lt;/li&gt;
&lt;li&gt;the Tk Windowing Toolkit is now included&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Ripper&lt;/span&gt; library to see how Ruby 1.9 parses Ruby to an AST&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Prime&lt;/span&gt; is a prime library&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Coverage&lt;/span&gt; library gives basic coverage stats for your code (must load file)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;&lt;span style="color: #87ffaf;"&gt;Coverage&lt;/span&gt;.start&lt;br /&gt;require_relative &lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;file&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;br /&gt;puts&amp;nbsp;&lt;span style="color: #87ffaf;"&gt;Coverage&lt;/span&gt;.result&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Gone from the Standard Library&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;date2&lt;/span&gt; (was a derivative of date)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ftools&lt;/span&gt;&amp;nbsp;library (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;FileUtils&lt;/span&gt; does what &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ftools&lt;/span&gt; used to do)&lt;/li&gt;
&lt;li&gt;The &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Generator&lt;/span&gt; class (we've got &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Enumerator&lt;/span&gt; now)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;getopts&lt;/span&gt; (we should use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;optparse&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;jcode&lt;/span&gt;&amp;nbsp;library (used to handle Japanese EUC/SJIS strings)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mailread&lt;/span&gt; library (use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;TMail&lt;/span&gt; instead)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;parsedate&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ping&lt;/span&gt; (used for TCP echoing)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;readbytes&lt;/span&gt; library&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RubyUnit&lt;/span&gt; (old way of doing unit testing)&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;New Syntax and misc elements&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;RUBY_VERSION&lt;/li&gt;
&lt;li&gt;RUBY_ENGINE&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&lt;span style="color: yellow;"&gt;&amp;gt; &lt;/span&gt;&amp;nbsp;&lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;my_method&lt;/b&gt;&lt;/span&gt;; p __callee__; &lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;; my_method&lt;br /&gt;&lt;span style="color: #ff40ff;"&gt;:my_method&lt;/span&gt;&lt;br /&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;:my_method&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;File::Stat#world_readable?&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#world_writable?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Many &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;File&lt;/span&gt; methods can use objects that implements a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;to_path&lt;/span&gt; method&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;a = []; &lt;span style="color: #5fd7ff;"&gt;def&lt;/span&gt;&amp;nbsp;a.&lt;span style="color: cyan;"&gt;&lt;b&gt;to_path&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;/etc/passwd&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;; &lt;span style="color: #5fd7ff;"&gt;end&lt;/span&gt;; &lt;span style="color: #87ffaf;"&gt;File&lt;/span&gt;.open(a)&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Object#id&lt;/span&gt; was deprecated and it's now removed. Use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#object_id&lt;/span&gt; instead&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Object#tap&lt;/span&gt; is a "passthrough" method for inspecting things&lt;/li&gt;
&lt;li&gt;Negative operators can now be defined/overridden (i.e. &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;!&lt;/span&gt;, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;!=&lt;/span&gt;, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;!~&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Splat operator enhanced (can be applied to non-last parameters, or have multiple splats on the right-hand side)&lt;/li&gt;
&lt;li&gt;Optional arguments can now appear before mandatory ones&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;a&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;..&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;z&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;).include?(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;car&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;false&lt;/span&gt;&lt;br /&gt;(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;a&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;..&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;z&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;).member?(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;car&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;false&lt;/span&gt;&lt;br /&gt;(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;a&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;..&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;z&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;).cover?(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;car&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;false&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Kernel#methods&lt;/span&gt; (and friends) now returns an array of symbols, not strings anymore&lt;/li&gt;
&lt;li&gt;Block args can no longer be instance variables, e.g. &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{|@x|}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;You can now spread methods chains across multiple lines&lt;/li&gt;
&lt;li&gt;You can also spread a ternary operation across multiple lines&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Object.superclass = BasicObject&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Method#source_location&lt;/span&gt; is much like &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Proc#source_location&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;useful to know if a method has been monkey patched&lt;/li&gt;
&lt;li&gt;Symbol supports &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#=~&lt;/span&gt;, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#!~&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#match&lt;/span&gt; (but does not return a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MatchData&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Symbol#to_i&lt;/span&gt; is no more&lt;/li&gt;
&lt;li&gt;Symbols get &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#&amp;lt;&lt;/span&gt; , &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#&amp;gt;&lt;/span&gt; , &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#&amp;lt;=&lt;/span&gt; , &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#&amp;gt;=&lt;/span&gt; for comparisons&lt;/li&gt;
&lt;li&gt;No more &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;when:&lt;/span&gt; in case blocks (use ; or newlines instead)&lt;/li&gt;
&lt;li&gt;No more colon on "if" (use ;, then, or newlines instead)&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Module#const_defined?&lt;/span&gt; now looks for the parameter in the ancestors too (use false to prevent that)&lt;/li&gt;
&lt;li&gt;Same applies for &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;const_get&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;method_defined?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Class#class_variable_set&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#class_variable_get&lt;/span&gt; are now public&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Object#define_singleton_method&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public_send&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public_method&lt;/span&gt; respect private definitions&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Class X; end;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;X.singleton_class == (class &amp;lt;&amp;lt; X; self; end)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;base64 is still there&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Process#daemon&lt;/span&gt; daemonizes the current process&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Process#spawn&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Complex(3,4) == (3 + 4.i)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Binding#eval(code_string)&lt;/span&gt; has been added, but &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;eval("name, binding)&lt;/span&gt; still works&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Float::INFINITY&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;sprintf(&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;%A&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;, &lt;span style="color: #ff40ff;"&gt;1.234&lt;/span&gt;) &lt;span style="color: cyan;"&gt;# hex floating point format&lt;/span&gt;&lt;br /&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;0X1.3BE76C8B43958P+0&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span class="Apple-style-span" style="color: yellow;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;no more retry in loops&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;new method: &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;respond_to_missing?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Garbage Collection&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;div&gt;
&lt;br /&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GC.count&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GC::Profiler&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ObjectSpace&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; module&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;garbage collection tweaking options (e.g. &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RUBY_GC_MALLOC_LIMIT&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;/div&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;Ruby 1.9.3 Specifics&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li style="font-family: inherit;"&gt;"load.c" patch to speed up requiring/loading files&lt;/li&gt;
&lt;li style="font-family: inherit;"&gt;Garbage collection parameters now can be set in the environment&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Pathname&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; and &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Date&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; libraries re-implemented in C for more performance&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Random.new.rand(1..10)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Random.rand(1..10)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;rand(1..10)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Time.now.strftime("%b %d", %Y %z %:z %::z)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#prepend&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;prepends a string in place&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#byteslice(range)&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; or &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String#byteslice(quantity, index)&lt;/span&gt;&lt;/li&gt;
&lt;li style="font-family: inherit;"&gt;io/console&lt;/li&gt;
&lt;li style="font-family: inherit;"&gt;joint GPL2-Ruby to a joint 2-clause BSD and Ruby license&lt;/li&gt;
&lt;li style="font-family: inherit;"&gt;OpenSSL has new maintainers&lt;/li&gt;
&lt;li style="font-family: inherit;"&gt;New encodings: cp950, cp951, UTF-16, UTF-32&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;nbsp;&amp;gt; &lt;span style="color: #87ffaf;"&gt;File&lt;/span&gt;::&lt;span style="color: #87ffaf;"&gt;NULL&lt;/span&gt;&lt;br /&gt;&amp;nbsp; =&amp;gt; &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;/dev/null&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: monospace;"&gt;matrix&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; library being improved&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: monospace;"&gt;net/http&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; now supports "100 Continue" status&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/E8mnLyU7Atg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/E8mnLyU7Atg/ruby-19-walkthrough-by-peter-cooper.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-XH75DP6gWkg/TsgeUlhy7HI/AAAAAAAAAVE/QIVIIbXrnyg/s72-c/Ruby+1.9+Walkthrough.jpg" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2011/11/ruby-19-walkthrough-by-peter-cooper.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-5680364237575269844</guid><pubDate>Thu, 17 Nov 2011 18:10:00 +0000</pubDate><atom:updated>2012-03-30T16:45:49.879-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><title>Node.js from Ryan Dahl (JS Conf 2009)</title><description>I'm a bit late with that one, but I wanted to have an overview of Node.js from the man behind it. So I watched the &lt;a href="http://jsconf.eu/2009/video_nodejs_by_ryan_dahl.html"&gt;presentation from Ryan Dahl at JS Conf Berlin 2009&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/--RmtsCVFnYs/Tsga7yiEntI/AAAAAAAAAU8/XfWaVUA9Vus/s1600/nodejs.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/--RmtsCVFnYs/Tsga7yiEntI/AAAAAAAAAU8/XfWaVUA9Vus/s1600/nodejs.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Here are my notes:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Apache vs nginx&lt;/b&gt; (as regards to request concurrency)&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Apache uses OS threads&lt;/li&gt;
&lt;li&gt;nginx uses an event loop&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;b&gt;Threads&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;context switching is not free&lt;/li&gt;
&lt;li&gt;it costs some CPU time&lt;/li&gt;
&lt;li&gt;each thread takes mem&lt;/li&gt;
&lt;li&gt;threads is not the right way to do concurrency&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
The solution for efficient concurrency is thus to use the event model and use callbacks. And javascript has that event model architecture. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Node.js design goals&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;no function should perform direct IO&lt;/li&gt;
&lt;li&gt;low level (stream everything, never forced to buffer)&lt;/li&gt;
&lt;li&gt;have built-in support for the most important protocols (TCP, DNS, HTTP)&lt;/li&gt;
&lt;li&gt;support many HTTP features (e.g. chunked requests and responses, keep-alive)&lt;/li&gt;
&lt;li&gt;friendly/intuitive API&lt;/li&gt;
&lt;li&gt;platform-independent&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
So the node.js project promotes a purely evented, non-blocking infrastructure to script highly concurrent programs. Its only dependency: python.&lt;br /&gt;
&lt;br /&gt;
Here is some sample code taken from the &lt;a href="http://nodejs.org/"&gt;node.js website&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;
&lt;span style="color: yellow;"&gt;1 &lt;/span&gt;var http = &lt;span style="color: #5fd7ff;"&gt;require&lt;/span&gt;(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;http&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;);&lt;br /&gt;
&lt;span style="color: yellow;"&gt;2 &lt;/span&gt;http.createServer(function (req, res) {&lt;br /&gt;
&lt;span style="color: yellow;"&gt;3 &lt;/span&gt;&amp;nbsp;&amp;nbsp;res.writeHead(&lt;span style="color: #ff40ff;"&gt;200&lt;/span&gt;, {&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;: &lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;text/plain&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;});&lt;br /&gt;
&lt;span style="color: yellow;"&gt;4 &lt;/span&gt;&amp;nbsp;&amp;nbsp;res.end(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Hello World\n&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: yellow;"&gt;5 &lt;/span&gt;}).listen(&lt;span style="color: #ff40ff;"&gt;1337&lt;/span&gt;, &lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;127.0.0.1&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: yellow;"&gt;6 &lt;/span&gt;console.log(&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;Server running at &lt;a href="http://127.0.0.1:1337/"&gt;http://127.0.0.1:1337/&lt;/a&gt;&lt;/span&gt;&lt;span style="color: #ffd7d7;"&gt;'&lt;/span&gt;);&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/24QCfFz1WV4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/24QCfFz1WV4/nodejs-from-ryan-dahl-js-conf-2009.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/--RmtsCVFnYs/Tsga7yiEntI/AAAAAAAAAU8/XfWaVUA9Vus/s72-c/nodejs.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2011/11/nodejs-from-ryan-dahl-js-conf-2009.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-8631744697191937000</guid><pubDate>Sun, 25 Jul 2010 02:10:00 +0000</pubDate><atom:updated>2012-05-29T14:34:27.112-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">OSX</category><category domain="http://www.blogger.com/atom/ns#">Unix</category><category domain="http://www.blogger.com/atom/ns#">Ubuntu</category><title>Write access to a HFS+ drive from Ubuntu</title><description>I wanted to have write access to my HFS+ external hard drive. It took me (frustrating) hours to find out, since I kept on having it mounted automagically (i.e. seconds after I inserted the USB plug in my labtop) as read-only. So I could read from it, but not write to it.&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;This &lt;a href="http://raamdev.com/mounting-hfs-with-write-access-in-debian"&gt;post&lt;/a&gt; did the trick for me. In other words, I had to install the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hfsprogs&lt;/span&gt; Ubuntu package and run:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;fsck.hfsplus [block device]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;so for me it was:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;fsck.hfsplus /dev/sdc6&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Nothing wrong was found after running that check, but it apparently needed to be run. Because right after, I unmounted it, and let it mount automagically, and it worked.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/8HMEoT3Di60" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/8HMEoT3Di60/write-access-to-hfs-drive-from-ubuntu.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>2</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2010/07/write-access-to-hfs-drive-from-ubuntu.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-4953820323011632940</guid><pubDate>Wed, 20 May 2009 23:19:00 +0000</pubDate><atom:updated>2009-05-20T16:19:49.335-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">git</category><title>Usecases using git log</title><description>I did a lightning talk (&amp;lt; 10 min) about 'git log' @ &lt;a href="http://www.montrealonrails.com/"&gt;Montreal.rb&lt;/a&gt; yesterday. My sources were &lt;a href="http://gitcasts.com/posts/git-log"&gt;Scott Chacon's git log screencast&lt;/a&gt;, &lt;a href="http://www.gitready.com/advanced/2009/01/20/bend-logs-to-your-will.html"&gt;Nick Quaranto's gitready post&lt;/a&gt;, as well as git-log manpages. Here are my notes:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Usecase: I want to be up to date with the latest activity&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -4&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --since="1 day"&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --since="2 hour"&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -2 --stat&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -2 --name-status&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --since='2009-05-05' --until='3 days'&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log i-2 --author='Martin C'&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log 9485fdd2..7b766227 # optionally specify a file&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Usecase: I want the latest changes on a specific file&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log [file] # gives you all commits for that specific file&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -3 [file] # gives you the 3 last commits&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -p [file] # gives you all diffs for every commit of that file&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -2 -p db/schema.rb&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git blame [file] # gives SHA1, author, line changed, app/controllers/questions_controller.rb&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Usecase: I want the changes of a commit you partly remember the comment&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --pretty=oneline | grep [comment &lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --grep='^user icon' &lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --grep='user icon' -i&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git show [SHA1]&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git show [SHA1]:[file &lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Usecase: I want stats on commits&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --pretty=oneline | wc -l&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --pretty=oneline --no-merges | wc -l&amp;nbsp; # no-merges: do not show commits that have more than 1 parent&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --pretty=oneline --author='Martin C' | wc -l&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --pretty=format:'%an' | sort | uniq -c | sort -n&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log --pretty=format:'%h by %an'&lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -4 --pretty=format:'%h (%H) by %an %ar (%ad) %s' &lt;/div&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;
git log -4 --pretty=format:'%h by %an %ar (%ad) %s' db/schema.rb &lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/dKu8lkuy6PE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/dKu8lkuy6PE/usecases-using-git-log.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/05/usecases-using-git-log.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-30376932968623696</guid><pubDate>Sat, 09 May 2009 18:10:00 +0000</pubDate><atom:updated>2009-05-15T11:37:10.140-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">railsconf 2009</category><title>RailsConf 2009: what to remember</title><description>I attended &lt;a href="http://railsconf.com/"&gt;RailsConf 2009&lt;/a&gt; and I'm quite happy about it. With close to 2 years into the Rails world, I wish some of the presentations were for a more advanced audience. The most interesting part was in the panels and keynotes.&lt;br /&gt;&lt;br /&gt;Note: a few presentations are available through &lt;a href="http://railsconf.blip.tv/"&gt;blip.tv&lt;/a&gt;. All in all, and somewhat briefly, what to remember from RailsConf 2009? If I had to choose 2 words to summarize it, I'd pick &lt;span style="font-weight: bold;"&gt;productivity&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;Rack&lt;/span&gt;. If you need more details, keep on reading!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Keynote by DHH&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Rails has been there for 5 years (2004-2009)&lt;br /&gt;Rails 3 will have:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;new routing&lt;/li&gt;&lt;li&gt;XSS&lt;/li&gt;&lt;li&gt;unobstrusive and agnostic JS&lt;/li&gt;&lt;li&gt;More agnosticism (e.g. ORM-agnostic)&lt;/li&gt;&lt;/ul&gt;The real secret to high productivity comes from "renegotiating the requirements", i.e. make sure the said requirements fulfill the need in its simplest form (which is very often different from the way it was originally expressed).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Keynote with DHH and Tim Ferris&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Although a lot of people didn't enjoy Tim Ferris' keynote (which was anything but terse, and seemingly too far beyond software engineering), there were nevertheless some points which were interesting.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Set rules for one's self&lt;/li&gt;&lt;/ul&gt;Tim Ferris explained that having very little time to do something forced him to set rules so that he could focus on the most important things. This resonates with &lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215"&gt;Eric Evans' conviction&lt;/a&gt; on identifying and subsequently focusing on the core business value. Or the idea that 80% of your time should be spent where your business has most value, and not only 20% of your time (as it is often the case).&lt;br /&gt;&lt;br /&gt;He also talked about 'lifestyle design' as opposed to 'deferred lifeplan' (having retirement as one of its assumption). I thought that this resonated with the concept of '&lt;a href="http://en.wikipedia.org/wiki/Lifestyle_business"&gt;lifestyle business&lt;/a&gt;'.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;convention over configuration&lt;/li&gt;&lt;/ul&gt;And here is a parallel with a core concept in Rails:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The idea of convention over configuration is a very appealing one because you want to have rules and rituals for everything that does not involve your core competencies, so that you can use your creative resources where they are most valuable.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;Information diet&lt;/li&gt;&lt;/ul&gt;The idea is to develop 'selected ignorance'. In our digital world, there is more accessible information that it is possible to digest. So we need to create barriers or filters in order to select.&lt;br /&gt;&lt;br /&gt;"If you look at how media/news is generated, the less you believe it's necessary to read it, partially because it's biased or inaccurate".&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Path to success?&lt;/li&gt;&lt;/ul&gt;Through all conversations he had with successful people in technology or in other domains, he consistently heard one piece of advice:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;There is no one path to success or productivity. It's very personal. But there is one path to be completely miserable [or failure], and that is trying to please everybody"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;br /&gt;Keynote by Chris Wanstrath&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Productivity&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;This idea of friction, it's a lot like the inverse of productivity. Being productive means getting things done efficiently and effectively. Friction keeps you from doing those things, slows you down, conspires against you, wastes energy.&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;Examples of productivity&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;Here are two of the most important investments you can make when starting a new business: having professionals file the paperwork and handle the numbers.&lt;/blockquote&gt;&lt;blockquote&gt;We all love Rails because it makes most of the tedious stuff go away.&lt;/blockquote&gt;&lt;blockquote&gt;And testing is famous because, well, bugs and bad design are the worst.&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;Focus on the community&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;So let's follow these examples. Let's create more projects that scratch an itch or ease some pain. Let's stop obsessing about which test framework to use and start obsessing about building sites that solve problems. Let's stop arguing about languages and continue improving our favorite ones. Let's stop blogging lengthy tutorials to get RSS subscribers and start contributing to official documentation efforts.&lt;/blockquote&gt;&lt;br /&gt;Keynote message: Let's focus more on code and less on talk. More on the community and less on ourselves.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Keynote by Robert Martin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If Tim Ferris' keynote was judged as the least appreciated keynote, uncle Bob's keynote was certainly the most appreciated. It was hailed as both entertaining and interesting. His keynote title was: "What killed SmallTalk and might kill Ruby?" Here are his answers:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;lack of discipline (specifically: using proper TDD)&lt;/li&gt;&lt;li&gt;arrogance, lack of humility ('us' vs 'them')&lt;/li&gt;&lt;li&gt;lack of acceptance to solve the dirty problems (those of the enterprise)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;In addition to that, some catchy phrases:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;SmallTalk epitomized what OO was about&lt;/li&gt;&lt;li&gt;SmallTalk was the most powerful language in the 70s and 80s&lt;br /&gt;&lt;/li&gt;&lt;li&gt;what is clean [code] today might not be clean [code] tomorrow&lt;/li&gt;&lt;li&gt;Tests eliminate fear&lt;/li&gt;&lt;li&gt;professionalism is the disciplined wielding of power&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Rack is the new cool kid&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Several talks during RailsConf were about Rack (which really is a very simple way to plug functionality before or/and after the handling of a web request), people were talking about it. There certainly was a buzz about Rack.&lt;br /&gt;&lt;br /&gt;Personally, I think Rack middleware is very similar to a ServletFilter in the filter chain, in the Java world. If you haven't played with Rack yet, the best introduction to Rack I could recommend is &lt;a href="http://rubymanor.org/videos/rack/"&gt;Dan Webb's 8-min presentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;Rails innovations&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Greg Pollack and Jason Seifer (&lt;a href="http://www.railsenvy.com/"&gt;RailsEnvy&lt;/a&gt; guys) gave a presentation about the Rails innovations in the last year. Here are the pieces of software worth mentioning:&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;RubyMine IDE&lt;/li&gt;&lt;li&gt;Rack&lt;/li&gt;&lt;li&gt;Rails metal&lt;/li&gt;&lt;li&gt;Rails templates&lt;/li&gt;&lt;li&gt;metric-fu gem&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Cucumber for BDD&lt;br /&gt;&lt;/li&gt;&lt;li&gt;FakeWeb &lt;/li&gt;&lt;li&gt;Spike (log analyser)&lt;/li&gt;&lt;li&gt;Ultrasphinx (full-text search)&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/F3i4UIp1V7E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/F3i4UIp1V7E/railsconf-2009-what-to-remember.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/05/railsconf-2009-what-to-remember.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-6167684171120601509</guid><pubDate>Thu, 07 May 2009 17:24:00 +0000</pubDate><atom:updated>2009-05-09T11:06:30.886-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">railsconf 2009</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><title>Agile development tips, by David W. Frank</title><description>I watched the talk from David W. Frank (from Pivotal Labs) at RailsConf. It was interesting to listen to advice on agile software development, although on some I would disagree. Here are my highlights and some thoughts afterwards.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Stick to conventions&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;follow the ground rules&lt;/li&gt;&lt;li&gt;be a lord of discipline&lt;/li&gt;&lt;li&gt;pop goes the story stack (pick the very first task on top)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Stay in sync&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;cubicules kill&lt;/li&gt;&lt;li&gt;go to lunch as a team&lt;/li&gt;&lt;li&gt;keep up the jibber jabber (talking while working)&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Tools matter&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;rtfw (or be quick to google it)&lt;/li&gt;&lt;li&gt;get stories done&lt;/li&gt;&lt;li&gt;this is a whiteboard&lt;/li&gt;&lt;li&gt;don't forget the hardware&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pair&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;live together, die alone&lt;/li&gt;&lt;li&gt;let the rookie type&lt;/li&gt;&lt;li&gt;pairs stink after 2 days&lt;/li&gt;&lt;li&gt;two pairs are better than one&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Test drive&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;beat the blews&lt;/li&gt;&lt;li&gt;tests, not comments&lt;/li&gt;&lt;li&gt;ping pong isn't just table tennis&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Check your dashboard&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;every failing test is sacred&lt;/li&gt;&lt;li&gt;fix first, ask questions later&lt;/li&gt;&lt;li&gt;slow suites are project heart disease&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Work simply&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;architecture is a 4-letter word ('test')&lt;br /&gt;&lt;/li&gt;&lt;li&gt;make it green, then clean it&lt;/li&gt;&lt;li&gt;check-in early and often&lt;/li&gt;&lt;li&gt;kill dead code dead&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;My thoughts&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;pop goes the story stack&lt;/li&gt;&lt;/ul&gt;Code ownership is generally a bad idea, but in reality you have deadlines, i.e time is a constraint. If you need to be effective, some tasks will be done much quickly if done by certain team members (it might not be yourself). You shouldn't refuse a task because it's a boring chore (pleonasm intended), you should refuse a task if you feel it would take you substantially more time than if it would be done by another team member.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;go to lunch as a team&lt;/li&gt;&lt;/ul&gt;But not all the time. Maybe 50% of the time? Lunch is a very important break during the day, and it can be relaxing (sometimes needed) to have lunch with some people outside of your team.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;keep up the jibber-jabber &lt;/li&gt;&lt;/ul&gt;Nah. Totally not. Go for open spaces, but no to the jibber-jabber. You need to interrupt another team member when you really can't deal with the issue yourself. That's why a chatting channel (e.g. campfire) is useful. People will go read it whenever they feel like it, instead of being interrupted in the middle of something.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;tests, not comments&lt;/li&gt;&lt;/ul&gt;Absolutely, yeah. Comments are code pollution, very often. If you feel you need to write a comment, it probably means you need to refactor or rename method/class names.&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/zawytRrt5Sk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/zawytRrt5Sk/agile-development-tips-by-david-w-frank.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>2</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/05/agile-development-tips-by-david-w-frank.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-6083260852580948198</guid><pubDate>Fri, 27 Mar 2009 21:50:00 +0000</pubDate><atom:updated>2009-03-27T14:50:03.594-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby quiz (easy)</category><title>Ruby quiz (easy) #10</title><description>&lt;span style="font-weight:bold;"&gt;Question&lt;/span&gt;: How do you make this line a one-liner?&lt;br /&gt;&lt;br /&gt;&lt;div class="codeSnippet"&gt;&lt;br /&gt;&lt;font face="monospace"&gt;&lt;br /&gt;value = compute_value&lt;br&gt;&lt;br /&gt;value = (value &amp;gt; &lt;font color="#00ff00"&gt;CONSTANT&lt;/font&gt;) ? value : &lt;font color="#00ff00"&gt;CONSTANT&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Solution&lt;/span&gt;:&lt;br /&gt;&lt;div class="codeSnippet"&gt;&lt;br /&gt;&lt;font face="monospace"&gt;&lt;br /&gt;value = [compute_value, &lt;font color="#00ff00"&gt;CONSTANT&lt;/font&gt;].max&lt;br&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br/&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/YEUryKVHU30" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/YEUryKVHU30/ruby-quiz-easy-10.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/03/ruby-quiz-easy-10.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-1550214534159161845</guid><pubDate>Wed, 25 Mar 2009 19:59:00 +0000</pubDate><atom:updated>2011-11-17T10:23:24.220-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">monkey-patching</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><category domain="http://www.blogger.com/atom/ns#">Ruby metaprogramming</category><title>Unobstrusive metaprogramming, by Sean O'Halpin</title><description>I watched &lt;a href="http://seanohalpin.github.com/"&gt;Sean O'Halpin&lt;/a&gt; 30-minute &lt;a href="http://rubymanor.org/videos/unobtrusive_metaprogramming/"&gt;Ruby Manor presentation&lt;/a&gt; (Nov 2008) called "Unobstrusive metaprogramming". He gave a few tricks about monkeypatching.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/_o0aANf43DII/ScqM02-RcUI/AAAAAAAAAUk/S1o3nGCiWiM/s1600-h/sean-ohalpin.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_o0aANf43DII/ScqM02-RcUI/AAAAAAAAAUk/S1o3nGCiWiM/s400/sean-ohalpin.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Here are my highlights.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Problems with monkey patching "the Rails way"&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;namespace pollution&lt;/li&gt;
&lt;li&gt;documentation pollution&amp;nbsp;&lt;/li&gt;
&lt;li&gt;cognitive pollution&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Case in point:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;&amp;gt;&amp;gt; [&lt;span style="color: lime;"&gt;Kernel&lt;/span&gt;, &lt;span style="color: lime;"&gt;Object&lt;/span&gt;, &lt;span style="color: lime;"&gt;Class&lt;/span&gt;, &lt;span style="color: lime;"&gt;Module&lt;/span&gt;].inject({}){|&lt;span style="color: cyan;"&gt;hash&lt;/span&gt;, &lt;span style="color: cyan;"&gt;klass&lt;/span&gt;|&amp;nbsp;hash[klass] = klass.methods.size; hash}&lt;br /&gt;=&amp;gt; {&lt;span style="color: lime;"&gt;Object&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;98&lt;/span&gt;, &lt;span style="color: lime;"&gt;Kernel&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;159&lt;/span&gt;, &lt;span style="color: lime;"&gt;Module&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;99&lt;/span&gt;, &lt;span style="color: lime;"&gt;Class&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;99&lt;/span&gt;}&lt;br /&gt;&amp;gt;&amp;gt; &lt;span style="color: #ff40ff;"&gt;require&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;active_support&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;br /&gt;=&amp;gt; &lt;span style="color: #ff6060;"&gt;true&lt;/span&gt;&lt;br /&gt;&amp;gt;&amp;gt; [&lt;span style="color: lime;"&gt;Kernel&lt;/span&gt;, &lt;span style="color: lime;"&gt;Object&lt;/span&gt;, &lt;span style="color: lime;"&gt;Class&lt;/span&gt;, &lt;span style="color: lime;"&gt;Module&lt;/span&gt;].inject({}){|&lt;span style="color: cyan;"&gt;hash&lt;/span&gt;, &lt;span style="color: cyan;"&gt;klass&lt;/span&gt;|&amp;nbsp;hash[klass] = klass.methods.size; hash}&lt;br /&gt;=&amp;gt; {&lt;span style="color: lime;"&gt;Object&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;187&lt;/span&gt;, &lt;span style="color: lime;"&gt;Kernel&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;225&lt;/span&gt;, &lt;span style="color: lime;"&gt;Module&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;188&lt;/span&gt;, &lt;span style="color: lime;"&gt;Class&lt;/span&gt;=&amp;gt;&lt;span style="color: #ff6060;"&gt;188&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Recommendations&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;indirect access (using functions)&lt;/li&gt;
&lt;li&gt;namespaces&lt;/li&gt;
&lt;li&gt;hide your mess&lt;/li&gt;
&lt;/ul&gt;
So for instance, instead of monkey patching the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Array&lt;/span&gt; object, we can do something like that:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;span style="font-family: monospace;"&gt;a = [[&lt;span style="color: #ff6060;"&gt;1&lt;/span&gt;,&lt;span style="color: #ff6060;"&gt;2&lt;/span&gt;,&lt;span style="color: #ff6060;"&gt;3&lt;/span&gt;,[&lt;span style="color: #ff6060;"&gt;4&lt;/span&gt;],&lt;span style="color: #ff6060;"&gt;5&lt;/span&gt;]]&lt;br /&gt;&lt;span style="color: lime;"&gt;Doodle&lt;/span&gt;::&lt;span style="color: lime;"&gt;Utils&lt;/span&gt;.flatten_with_1_level(a) &lt;span style="color: #8080ff;"&gt;# =&amp;gt; [1,2,3,[4],5]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;The plea&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Don't monkeypatch: Object, Kernel, Module, Class, Hash, Array, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
Everytime you monkeypatch Object, a kitten dies.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/hEpkVYBh3Zs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/hEpkVYBh3Zs/unobstrusive-metaprogramming-by-sean.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_o0aANf43DII/ScqM02-RcUI/AAAAAAAAAUk/S1o3nGCiWiM/s72-c/sean-ohalpin.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/03/unobstrusive-metaprogramming-by-sean.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-5765627906163325248</guid><pubDate>Thu, 12 Mar 2009 22:36:00 +0000</pubDate><atom:updated>2009-03-26T08:02:19.852-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">projects</category><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">scrubyt</category><title>Hashtweeps scraper: mixed feelings about Scrubyt</title><description>&lt;span style="font-size: large;"&gt;&lt;b&gt;Motivation&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hashtweeps.com/"&gt;Hashtweeps&lt;/a&gt; is a simple site where you can search all tweets with a specific hash term. I have decided to give &lt;a href="http://scrubyt.org/"&gt;Scrubyt&lt;/a&gt; a go and write a little &lt;a href="http://hashtweeps.com/"&gt;Hashtweeps&lt;/a&gt; scraper to get a feel of it. The CEO of the company where I am at was at the leadscon conference, so I was challenged to gather all tweets with the leadscon hash (#leadscon).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The code&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="codeSnippet"&gt;&lt;font face="monospace"&gt;&lt;br /&gt;&lt;font color="#ff40ff"&gt;require&lt;/font&gt;&amp;nbsp;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;rubygems&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;font color="#ff40ff"&gt;require&lt;/font&gt;&amp;nbsp;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;scrubyt&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;font color="#00ff00"&gt;HASH_TERM&lt;/font&gt;&amp;nbsp;= &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;leadscon&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;data = &lt;font color="#00ff00"&gt;Scrubyt&lt;/font&gt;::&lt;font color="#00ff00"&gt;Extractor&lt;/font&gt;.define &lt;font color="#ffff00"&gt;do&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;fetch &lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;&lt;a href="http://www.hashtweeps.com/"&gt;http://www.hashtweeps.com/&lt;/a&gt;&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;fill_textfield &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;term&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;, &lt;font color="#00ff00"&gt;HASH_TERM&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;submit&lt;br&gt;&lt;br /&gt;&lt;br&gt;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#8080ff"&gt;# build XML structure&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;item &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//li[@class='result']&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;do&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//div[@class='msg']&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;link &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//div[@class='info']/a[1]/@href&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;user &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//div[@class='info']/a[1]&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;, &lt;font color="#ff6060"&gt;:generalize&lt;/font&gt;&amp;nbsp;=&amp;gt; &lt;font color="#ff6060"&gt;false&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;do&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#8080ff"&gt;# this will follow link because it ends with &amp;quot;_detail&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;page_detail &lt;font color="#ffff00"&gt;do&lt;/font&gt;&amp;nbsp;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;profile_info &lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;//ul[@class=&amp;quot;about vcard entry-author&amp;quot;]&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&amp;nbsp;&lt;font color="#ffff00"&gt;do&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;full_name &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//li//span[@class='fn']&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;location &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//li//span[@class='adr']&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;website &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//li//a[@class='url']/@href&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bio &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;//li//span[@class='bio']&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;end&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;end&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;end&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;end&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;end&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;font color="#8080ff"&gt;# dump XML to file&lt;/font&gt;&lt;br&gt;&lt;br /&gt;dump = &lt;font color="#00ff00"&gt;File&lt;/font&gt;.new(&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;output.xml&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;, &lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff6060"&gt;w&lt;/font&gt;&lt;font color="#ff40ff"&gt;&amp;quot;&lt;/font&gt;)&lt;br&gt;&lt;br /&gt;dump.puts data.to_xml&lt;br&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Screenshot of my output&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I added a very simple XSLT to my XML output and here it is:&lt;br/&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_o0aANf43DII/SbWaJrTm95I/AAAAAAAAAUc/4AA7Ev2BaWc/s1600-h/hashtweeps-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_o0aANf43DII/SbWaJrTm95I/AAAAAAAAAUc/4AA7Ev2BaWc/s400/hashtweeps-screenshot.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Scrubyt: Pros&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;All in one: navigator, extractor, output builder.&lt;/b&gt; With very few lines of code, you can write a simple scraper which can navigate pages, scrape and build/output a custom XML structure.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Scrubyt: &lt;/b&gt;&lt;b&gt;Cons&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Lack of a &lt;span style="font-style:italic;"&gt;good&lt;/span&gt; API reference.&lt;/b&gt; I had issues with the &lt;a href="http://wiki.scrubyt.org/index.php?title=Reference"&gt;official one&lt;/a&gt;. How am I supposed to know that if you end your method with "_detail" it will navigate to that page? It seems hard to ge beyond the "scrape Google results"-type of scenario. Indeed, there's lots of TODO's in the reference. Hopefully this reference will get more structure and coverage.&lt;/li&gt;&lt;li&gt;&lt;b&gt;No debug info.&lt;/b&gt; Even though the code above is fairly simple, when it breaks, you have no idea what the error was: Scrubyt just exits.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Impossible to test.&lt;/b&gt;&amp;nbsp;How do you make sure the second page you navigate still exists? How do you make sure the HTML elements are still where you thought they were? How do you make sure your code constructs the XML structure as you want it to be?&lt;/li&gt;&lt;li&gt;&lt;b&gt;The dependencies are not harnessed.&lt;/b&gt; I am a fan of having tight control on dependencies' versions. I wasted time to figure out that Scrubyt could not run with the (latest) version of the Mechanize gem I had installed.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The unofficial doc is outdated.&lt;/b&gt; Tutorials are nice when you want to get a first feel of a new tool. Unfortunately, probably because the Scrubyt source code has been changing a lot in the last year, Scrubyt tutorials out there are no more accurate. Remedy: the first stop to kick start your first scraper should be the &lt;a href="http://wiki.scrubyt.org/index.php?title=Tutorials"&gt;tutorials on Scrubyt's wiki&lt;/a&gt;.&amp;nbsp; &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you're serious about scraping, scrubyt is not a viable option. As soon as you're beyond the trivial scraper (like the one I did), you're in for some waste of your time.&lt;br /&gt;&lt;br/&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/cqerEDFV0Lg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/cqerEDFV0Lg/hashtweeps-scraper-mixed-feelings-about.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_o0aANf43DII/SbWaJrTm95I/AAAAAAAAAUc/4AA7Ev2BaWc/s72-c/hashtweeps-screenshot.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/03/hashtweeps-scraper-mixed-feelings-about.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-2198297185696483348</guid><pubDate>Thu, 05 Mar 2009 23:49:00 +0000</pubDate><atom:updated>2009-03-10T07:11:29.697-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JRuby</category><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">MRI</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><title>Ruby VM's, by Jason Seifer</title><description>I watched Jason Seifer's QCon 30-min &lt;a href="http://www.infoq.com/presentations/seifer-ruby-vm-comparison"&gt;presentation on Ruby VM's&lt;/a&gt;. He describes the main characteristics of most Ruby VM's out there. A little note: his criterium to decide whether a VM is production-ready or not is based on its support (or lack of support) for Rails, since that's a Ruby framework which touches on a lot of aspects of the Ruby implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/_o0aANf43DII/SbBkAyyGbtI/AAAAAAAAAUU/I7Ze8Ml_i0o/s1600-h/ruby-vms-jason-seifer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_o0aANf43DII/SbBkAyyGbtI/AAAAAAAAAUU/I7Ze8Ml_i0o/s320/ruby-vms-jason-seifer.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Here are my highlights.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ruby versions&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Ruby 1.8.6 is the most widespread implementation&lt;/li&gt;
&lt;li&gt;Ruby 1.8.7 is the current stable version of Ruby (middle ground between 1.8.6 and 1.9)&lt;/li&gt;
&lt;li&gt;all VM's focus on Ruby 1.8.6 (with the exception of JRuby, which has support for both Ruby 1.8.6 and Ruby 1.9)&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;MRI&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;i&gt;de facto&lt;/i&gt; standard&lt;/li&gt;
&lt;li&gt;the only concise Ruby spec out there&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;supported by all major platforms&lt;/li&gt;
&lt;li&gt;production-ready&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;YARV&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Ruby 1.9.1 will have YARV as the default VM&lt;/li&gt;
&lt;li&gt;not production-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;MacRuby&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Ruby 1.9 VM on OS X core technologies&lt;/li&gt;
&lt;li&gt;mostly uses Objective-C and YARV C code&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;open source&lt;/li&gt;
&lt;li&gt;early in development (&amp;lt; 1.0 release)&lt;/li&gt;
&lt;li&gt;not production-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;XRuby&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;first Ruby to Java compiler&lt;/li&gt;
&lt;li&gt;last release: 0.3 in Nov 2007&lt;/li&gt;
&lt;li&gt;not production-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;MagLev&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;not released yet&lt;/li&gt;
&lt;li&gt;made by GemStone&lt;/li&gt;
&lt;li&gt;uses OODB (allow Ruby objects persistence)&lt;/li&gt;
&lt;li&gt;not production-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;Rubinius&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;"Ruby in Ruby" (since part of it is written in Ruby)&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;the VM proper is written in C++&lt;/li&gt;
&lt;li&gt;the standard lib written in Ruby &lt;/li&gt;
&lt;li&gt;Ruby objects mapped to a C++ object&lt;/li&gt;
&lt;li&gt;migration from C to C++ was for lowering the barrier of entry for project contribution&lt;/li&gt;
&lt;li&gt;slow&lt;/li&gt;
&lt;li&gt;best of the MRI contenders&lt;/li&gt;
&lt;li&gt;Ruby spec project came out of Rubinius&lt;/li&gt;
&lt;li&gt;not production-ready&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;IronRuby&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft's implementation of Ruby&lt;/li&gt;
&lt;li&gt;Ruby on .Net&lt;/li&gt;
&lt;li&gt;released under MPL (Microsoft Public Library)&lt;/li&gt;
&lt;li&gt;runs on the DLR (Dynamic Language Runtime), on top of the CLR&lt;/li&gt;
&lt;li&gt;DLR supported languages: IronPython, IronRuby, Javascript, Dynamic&lt;/li&gt;
&lt;li&gt;not production-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;JRuby&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;big advantage: can use existing Java code&lt;/li&gt;
&lt;li&gt;most performant Ruby implementation&lt;/li&gt;
&lt;li&gt;multi-threaded (native ones, i.e. it threads in different processes)&lt;/li&gt;
&lt;li&gt;introduced a compatibiltiy land (can start the VM with a Ruby 1.8 or 1.9 "compatibility flag")&lt;/li&gt;
&lt;li&gt;The solution for the enterprise-class Ruby applications&lt;/li&gt;
&lt;li&gt;production-ready (!)&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/ZUnRbggZDSc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/ZUnRbggZDSc/ruby-vms-by-jason-seifer.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_o0aANf43DII/SbBkAyyGbtI/AAAAAAAAAUU/I7Ze8Ml_i0o/s72-c/ruby-vms-jason-seifer.png" height="72" width="72" /><thr:total>9</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/03/ruby-vms-by-jason-seifer.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-1129725997648093637</guid><pubDate>Thu, 12 Feb 2009 15:53:00 +0000</pubDate><atom:updated>2009-02-12T09:29:20.859-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">presentation</category><category domain="http://www.blogger.com/atom/ns#">doing cool stuff</category><title>My journey towards CouchDB, by Damien Katz</title><description>I watched the &lt;a href="http://www.infoq.com/presentations/katz-couchdb-and-me"&gt;presentation&lt;/a&gt; that Damien Katz (the one behind &lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt;) gave at RubyFringe in 2008. The presentation is a non-technical and inspirational description of his journey to be able to live off "doing cool stuff", which for him is to write open source software.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://4.bp.blogspot.com/_o0aANf43DII/SZRMp7pOPAI/AAAAAAAAATY/2IL-yAhe5II/s1600-h/damien-katz.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5301946944590855170" src="http://4.bp.blogspot.com/_o0aANf43DII/SZRMp7pOPAI/AAAAAAAAATY/2IL-yAhe5II/s400/damien-katz.jpg" style="cursor: pointer; display: block; height: 239px; margin: 0px auto 10px; text-align: center; width: 321px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Here are my highlights.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Reasons for doing "cool stuff"&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;educational&lt;/li&gt;
&lt;li&gt;more family time&lt;/li&gt;
&lt;li&gt;see what I can do&lt;/li&gt;
&lt;li&gt;makes an interesting story&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt; Java vs Erlang&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
One of the rare technical bits was that comparative slide:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/_o0aANf43DII/SZRJ799MV4I/AAAAAAAAATQ/Pl417tXkI-E/s1600-h/erlang-vs-java.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5301943955914250114" src="http://2.bp.blogspot.com/_o0aANf43DII/SZRJ799MV4I/AAAAAAAAATQ/Pl417tXkI-E/s400/erlang-vs-java.jpg" style="cursor: pointer; display: block; height: 309px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;
A very tough journey towards happiness&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
It was &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; hard to take off and risk to jeopardize his family for "doing crazy stuff". It took him a long time to get there; he went through highs and lows; he had to make sacrifices. That might be why so few people are willing to do it.&lt;br /&gt;
&lt;br /&gt;
But today he can proudly say:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
I'm that guy who gets paid to work on cool stuff from home.&lt;span style="font-style: italic;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
There are no predetermined steps to reach this state of mind, this kind of living style. It is an intrinsically personal process which is discovered as one goes through it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;A requestioning of the status quo&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/_o0aANf43DII/SZRZz3ij-6I/AAAAAAAAATg/-6kdTTSMOug/s1600-h/cool-stuff-why-not-me.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_o0aANf43DII/SZRZz3ij-6I/AAAAAAAAATg/-6kdTTSMOug/s400/cool-stuff-why-not-me.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/7Ehy2BC2Wrg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/7Ehy2BC2Wrg/my-journey-towards-couchdb-by-damien.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_o0aANf43DII/SZRMp7pOPAI/AAAAAAAAATY/2IL-yAhe5II/s72-c/damien-katz.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/02/my-journey-towards-couchdb-by-damien.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-8939164415391875264</guid><pubDate>Tue, 03 Feb 2009 18:28:00 +0000</pubDate><atom:updated>2009-02-03T10:37:50.439-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby quiz (easy)</category><title>Ruby quiz (easy) #9</title><description>&lt;b&gt;Question&lt;/b&gt;: What will be the output of the following snippet:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;&lt;font face="monospace"&gt;&lt;br /&gt;
&lt;font color="#ff40ff"&gt;require&lt;/font&gt;&amp;nbsp;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;rubygems&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;font color="#ff40ff"&gt;require&lt;/font&gt;&amp;nbsp;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;fileutils&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
puts &lt;font color="#00ff00"&gt;File&lt;/font&gt;.expand_path(&lt;font color="#00ff00"&gt;File&lt;/font&gt;.dirname(&lt;font color="#ff6060"&gt;__FILE__&lt;/font&gt;))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;font color="#00ff00"&gt;FileUtils&lt;/font&gt;.mkdir &lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;test&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;font color="#00ff00"&gt;FileUtils&lt;/font&gt;.chdir &lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;font color="#ff6060"&gt;test&lt;/font&gt;&lt;font color="#ff40ff"&gt;'&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
puts &lt;font color="#00ff00"&gt;File&lt;/font&gt;.expand_path(&lt;font color="#00ff00"&gt;File&lt;/font&gt;.dirname(&lt;font color="#ff6060"&gt;__FILE__&lt;/font&gt;))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Solution&lt;/b&gt;:&lt;br /&gt;
If run in user's account, the output will be:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
/home/user&lt;br /&gt;
/home/user/test&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Surprised? So was I.&lt;br&gt;&lt;br&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/AHuJX75iTmk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/AHuJX75iTmk/ruby-quiz-easy-9.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/02/ruby-quiz-easy-9.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-8259790869267536106</guid><pubDate>Wed, 28 Jan 2009 23:16:00 +0000</pubDate><atom:updated>2009-01-28T16:38:06.894-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">presentation</category><title>What Makes Code Beautiful?, by Marcel Molina, Jr.</title><description>I watched &lt;a href="http://rubyconf2007.confreaks.com/d1t1p1_what_makes_code_beautiful.html"&gt;What Makes Code Beautiful?&lt;/a&gt;, a presentation &lt;a href="http://www.vernix.org/marcel/"&gt;Marcel Molina Jr.&lt;/a&gt; gave at RubyConf '07.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_o0aANf43DII/SYD1LQ_nopI/AAAAAAAAATI/cQeDKQ6HknA/s1600-h/beauty-molina.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_o0aANf43DII/SYD1LQ_nopI/AAAAAAAAATI/cQeDKQ6HknA/s400/beauty-molina.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Here are my highlights.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;A definition of beauty&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
From all the definitions of beauty he explored, he chose the one from Thomas Aquinas, where beauty is defined with 3 criteria:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;proportion (economy of size: smallest size needed to do the job)&lt;/li&gt;
&lt;li&gt;integrity (faculty of being well suited for its purpose)&lt;/li&gt;
&lt;li&gt;clarity (simple and clear)&lt;/li&gt;
&lt;/ul&gt;Each of those 3 criteria is necessary, and none are sufficient.&lt;br /&gt;
&lt;br /&gt;
The idea is to apply those criteria to our code, so that it becomes 'beautiful'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;A definition of expert&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
He dropped in an interesting quote from a famous physicist:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;An expert is a person who has made all the mistakes that can be made in a very narrow field. -&lt;i&gt;Niels Bohr&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;
In other words, by accumulating mistakes, you gain expertise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Ruby == beautiful&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
At the end, Marcel Molina enthusiastically encourages the crowd to give a a warm applause to Matz, sitting in the front row, for the beautiful programming language he has created.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/UZ21gToX5rQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/UZ21gToX5rQ/what-makes-code-beautiful-by-marcel.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_o0aANf43DII/SYD1LQ_nopI/AAAAAAAAATI/cQeDKQ6HknA/s72-c/beauty-molina.gif" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/01/what-makes-code-beautiful-by-marcel.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-699647072994579007</guid><pubDate>Tue, 27 Jan 2009 17:30:00 +0000</pubDate><atom:updated>2009-01-30T05:36:19.751-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">projects</category><category domain="http://www.blogger.com/atom/ns#">context</category><category domain="http://www.blogger.com/atom/ns#">Ruby</category><category domain="http://www.blogger.com/atom/ns#">RSpec</category><category domain="http://www.blogger.com/atom/ns#">testing</category><category domain="http://www.blogger.com/atom/ns#">Shoes</category><category domain="http://www.blogger.com/atom/ns#">Sinatra</category><title>Ric-rac-roe in a soup of technologies</title><description>It all started with a desire to experiment a few things: &lt;a href="http://sinatra.github.com/"&gt;Sinatra&lt;/a&gt;, &lt;a href="http://www.shoooes.net/"&gt;Shoes&lt;/a&gt;, and the &lt;a href="http://github.com/jeremymcanally/context/tree/master"&gt;context&lt;/a&gt; testing framework.  So I decided to write a simple application - the classic tic-tac-toe game. I ended up with 3 interfaces:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;command line interface (cli)  &lt;/li&gt;&lt;li&gt;web app (using Sinatra)  &lt;/li&gt;&lt;li&gt;GUI desktop app (using Shoes)  &lt;/li&gt;&lt;/ul&gt;I thought it'd be nice to give a little feedback on my experience.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:large;"&gt;Ric-rac-roe: the app&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I tried to write 'nice Ruby code', that is, readable/intuitive code along side tests (as a result of TDD, but complemented so that it serves as API doc). You can &lt;a href="http://github.com/cawel/ric-rac-roe/tree/master"&gt;check the code out&lt;/a&gt; on github.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Design &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1 &lt;span style=""&gt;Grid&lt;/span&gt; model for the 9 squares of the tic-tac-toe as well as its rules (e.g. check for winning position, only play in an empty square, etc.). 1 &lt;span style=""&gt;Game&lt;/span&gt; model so that a gameplay can interact with the tic-tac-toe grid (via the &lt;span style=""&gt;Game#play&lt;/span&gt; method). The contract for the gameplay is to define 3 methods, which will be called at each turn&lt;span style=""&gt;&lt;/span&gt; (from the &lt;span style=""&gt;Game#play&lt;/span&gt; method):&lt;br /&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;position(position)    #reads the player's move&lt;br /&gt;&lt;/li&gt;&lt;li&gt;status_message=(msg)  #sets the status message&lt;br /&gt;&lt;/li&gt;&lt;li&gt;squares=(squares)     #sets the grid's squares&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;There currently exists 3 gameplays: CLI, web and desktop.&lt;br /&gt;&lt;br /&gt;The classes diagram could look like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_o0aANf43DII/SX8gBPAU9LI/AAAAAAAAATA/JzSBXB38wrU/s1600-h/class-dia-rrr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_o0aANf43DII/SX8gBPAU9LI/AAAAAAAAATA/JzSBXB38wrU/s400/class-dia-rrr.png" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Stats&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;(non-tests, non-views) LOC: 345&lt;br /&gt;&lt;/li&gt;&lt;li&gt;tests LOC: 308&lt;/li&gt;&lt;li&gt;&lt;a href="http://eigenclass.org/hiki.rb?rcov#l15"&gt;C0 code coverage&lt;/a&gt;: 98%&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;&lt;b&gt;Sinatra&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I must say it was a joy to write Sinatra code. Quick, easy and fun. I'm aware my app is quite simple, but the light nature and the hands-off approach of Sinatra fit my tic-tac-toe project perfectly.&lt;br /&gt;&lt;b&gt;  &lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_o0aANf43DII/SX3ddTxhwrI/AAAAAAAAASw/2kpGeDjMjo0/s1600-h/rrr.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_o0aANf43DII/SX3ddTxhwrI/AAAAAAAAASw/2kpGeDjMjo0/s400/rrr.gif" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Support from the Sinatra community&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sinatra.github.com/api/index.html"&gt;Sinatra's Rdoc&lt;/a&gt; got me started real quick. No waste of time. On their #sinatra IRC channel, &lt;a href="http://tomayko.com/"&gt;Ryan Tomayko&lt;/a&gt;, one of Sinatra lead developers, as well as some others, were there to assist on a few occasions. Lots of nice people in there, good vibe.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:large;" &gt;Shoes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Booting up my first Shoes app was also easy, but it took me more time.&lt;br /&gt;&lt;br /&gt;The development is intuitive because the layout management for your components is done web-style, with margin, padding, colors, etc. for components that you toss into either stacks (akin to usual block div's) or flows (akin to inline div's). You define your callbacks (like a click handler on a button) with a Ruby  block appended to the button's click method. So you get the drift. It starts to feel natural, after a little getting used to.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_o0aANf43DII/SX3sN2SDbNI/AAAAAAAAAS4/nY3Q5o1Zm-E/s1600-h/rrr-shoes.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_o0aANf43DII/SX3sN2SDbNI/AAAAAAAAAS4/nY3Q5o1Zm-E/s400/rrr-shoes.gif" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Support from the Shoes community&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The IRC channel #shoes is as quiet as a cemetery when it's -35 C.  &lt;a href="http://greatseth.com/"&gt;Seth Thomas Rasmussen&lt;/a&gt; seems to be the only one active in there, and he is the one who helped me out (and some others) with my newbe questions. I thought I'd see _why hanging in there, but according to Seth, he hasn't hanged in there for months. No doubt, busy elsewhere. But he's actively working on Shoes (and &lt;a href="http://www.rubyinside.com/shoes-roundup-ruby-gui-app-development-goodness-597.html"&gt;has been for a long time&lt;/a&gt;), when you look at the &lt;a href="http://github.com/why/shoes/commits/master/"&gt;github's project history&lt;/a&gt;. As for the &lt;a href="http://news.gmane.org/gmane.comp.lib.shoes"&gt;Shoes mailing-list&lt;/a&gt;, there's medium activity (circa 1 mail per day).&lt;br /&gt;&lt;br /&gt;The neat built-in manual (which comes with the Shoes installer) is your best way to find your answers; you don't need much else. Finally, perusing through &lt;a href="http://github.com/why/shoes/tree/master/samples"&gt;a few sample apps&lt;/a&gt; is a great way to get some source code inspiration.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;&lt;b&gt;Context&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I read &lt;a href="http://jamesgolick.com/2009/1/16/one-line-tests-without-the-smells"&gt;a&lt;/a&gt; &lt;a href="http://marktucks.blogspot.com/2008/12/unit-testing-using-context.html"&gt;few&lt;/a&gt; &lt;a href="http://evang.eli.st/blog/2009/1/15/how-i-test-controllers-2009-remix"&gt;interesting&lt;/a&gt; &lt;a href="http://giantrobots.thoughtbot.com/2008/11/7/a-critical-look-at-the-current-state-of-ruby-testing"&gt;posts&lt;/a&gt; on testing frameworks, with a focus on &lt;a href="http://github.com/jeremymcanally/context/tree/master"&gt;context&lt;/a&gt;. I wanted to try it, and enjoyed it. All it requires is &lt;span style=""&gt;test/unit&lt;/span&gt; and you can have contexts in your tests, and play it a la BDD, RSpec-style (describe/it), shoulda-style (context/should), or context-style (context/test) it doesn't matter. With context, you can mix all that, and have the context/it flavor if you will, without even including RSpec.&lt;br /&gt;&lt;br /&gt;I ended up using pure test/unit in some places (e.g. testing simple input parsing, or my &lt;span style=""&gt;Array&lt;/span&gt;'s monkeypatch), RSpec in some others (e.g. testing Sinatra's routes).  And in either situations sometimes I found I needed contexts on top of test/unit. So it all depends on what you want to do, it just felt good to use the most appropriate tool of my tools belt, depending on the context (no pun intended).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;&lt;b&gt;Final words&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Overall, I had a good time, and now I'm happy to know a bit more about quality tools. Any feedback on the code is welcome (design-wise, Ruby-wise,  testing-wise, etc.).&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/QQHuh6TgEsc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/QQHuh6TgEsc/ric-rac-roe-in-soup-of-technologies.html</link><author>noreply@blogger.com (Martin Carel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_o0aANf43DII/SX8gBPAU9LI/AAAAAAAAATA/JzSBXB38wrU/s72-c/class-dia-rrr.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/01/ric-rac-roe-in-soup-of-technologies.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-4273160011815580963</guid><pubDate>Sat, 24 Jan 2009 04:34:00 +0000</pubDate><atom:updated>2011-11-22T09:26:45.599-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby quiz (easy)</category><title>Ruby quiz (easy) #8</title><description>&lt;span style="font-weight: bold;"&gt;Question&lt;/span&gt;: What would be the output of this code snippet (note the type of the key in the hash and the type of the key when accessing the hash):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;br /&gt;
&lt;span style="font-family: monospace;"&gt;&lt;br /&gt;hash = {&lt;span style="color: #ff6060;"&gt;:language&lt;/span&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;ruby&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;, &lt;span style="color: #ff6060;"&gt;:author&lt;/span&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;martin&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;}&lt;br /&gt;&lt;br /&gt;p hash[&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;language&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
The output is &lt;code&gt;nil&lt;/code&gt; because the hash is defined using symbols, and the access to it was done using a string.&lt;br /&gt;
&lt;br /&gt;
Rails' active_support introduced a class called &lt;code&gt;HashWithIndifferentAccess&lt;/code&gt; (a subclass of &lt;code&gt;Hash&lt;/code&gt;), which, according to the class' doc:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
[...] we only have it so that people can write params[:key] instead of params[‘key’] and they get the same value for both keys.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
Referring back to the example above, we could get what we want (indifference between symbol or string hash access) with:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="codeSnippet"&gt;
&lt;br /&gt;
&lt;span style="font-family: monospace;"&gt;&lt;br /&gt;&lt;span style="color: #ff40ff;"&gt;require&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;rubygems&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff40ff;"&gt;require&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;active_support&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;hash = &lt;span style="color: lime;"&gt;HashWithIndifferentAccess&lt;/span&gt;.new({&lt;span style="color: #ff6060;"&gt;:language&lt;/span&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;ruby&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;, &lt;span style="color: #ff6060;"&gt;:author&lt;/span&gt;&amp;nbsp;=&amp;gt; &lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;martin&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;})&lt;br /&gt;&lt;br /&gt;p hash[&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;&lt;span style="color: #ff6060;"&gt;language&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;'&lt;/span&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
which would print &lt;code&gt;"ruby"&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/4nKW3BwqXiI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/4nKW3BwqXiI/ruby-quiz-easy-8.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>1</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/01/ruby-quiz-easy-8.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-2919778532453224045</guid><pubDate>Thu, 22 Jan 2009 20:45:00 +0000</pubDate><atom:updated>2009-01-22T13:20:52.988-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ruby quiz (easy)</category><title>Ruby quiz (easy) #7</title><description>&lt;span style="font-weight:bold;"&gt;Question&lt;/span&gt;: What would be the output of this code snippet?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="codeSnippet"&gt;&lt;br /&gt;&lt;font face="monospace"&gt;&lt;br /&gt;ary = [&lt;font color="#ff6060"&gt;1&lt;/font&gt;,&lt;font color="#ff6060"&gt;2&lt;/font&gt;,&lt;font color="#ff6060"&gt;3&lt;/font&gt;]&lt;br&gt;&lt;br /&gt;ary.each &lt;font color="#ffff00"&gt;do&lt;/font&gt;&amp;nbsp;|&lt;font color="#00ffff"&gt;element&lt;/font&gt;|&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;element += &lt;font color="#ff6060"&gt;1&lt;/font&gt;&lt;br&gt;&lt;br /&gt;&lt;font color="#ffff00"&gt;end&lt;/font&gt;&lt;br&gt;&lt;br /&gt;p ary&lt;br&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Solution&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;The output would be &lt;code&gt;[1, 2, 3]&lt;/code&gt;. The entire array is not modified by the &lt;code&gt;Array#each method&lt;/code&gt;. This is because the iterator, while traversing the collection, passes a copy of each element in turn, to the block. &lt;br /&gt;&lt;br /&gt;If you want to dig a bit, if you look in the C code from Ruby 1.8.4 in the &lt;a href="http://www.ruby-doc.org/doxygen/1.8.4/array_8c-source.html"&gt;array.c file&lt;/a&gt;, the parameter  yielded to the block is passed "by value", as opposed to "by address" (which would then allow modification of its value).&lt;br /&gt;&lt;br /&gt;&lt;div class="codeSnippet"&gt;&lt;br /&gt;&lt;font face="monospace"&gt;&lt;br /&gt;VALUE&lt;br&gt;&lt;br /&gt;rb_ary_each(ary)&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;VALUE ary;&lt;br&gt;&lt;br /&gt;{&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#00ff00"&gt;long&lt;/font&gt;&amp;nbsp;i;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;for&lt;/font&gt;&amp;nbsp;(i=&lt;font color="#ff6060"&gt;0&lt;/font&gt;; i&amp;lt;RARRAY(ary)-&amp;gt;len; i++) {&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rb_yield(RARRAY(ary)-&amp;gt;ptr[i]);&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#ffff00"&gt;return&lt;/font&gt;&amp;nbsp;ary;&lt;br&gt;&lt;br /&gt;}&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://feeds.feedburner.com/~r/dev-logger/~4/egST11xIxto" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/dev-logger/~3/egST11xIxto/ruby-quiz-easy-7.html</link><author>noreply@blogger.com (Martin Carel)</author><thr:total>0</thr:total><feedburner:origLink>http://dev-logger.blogspot.com/2009/01/ruby-quiz-easy-7.html</feedburner:origLink></item></channel></rss>
