Gray Soft / My Projects / Getting FasterCSV Ready for Ruby 1.9tag:graysoftinc.com,2014-03-20:/posts/422014-04-05T16:14:36ZJames Edward Gray IIThe 33rd Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-07-10:/comments/3852014-04-05T16:14:36Z&gt;When Ruby 1.8 was on the horizon and 1.6 was the normal version for people to use, someone created a library called &quot;shim&quot;, which allowed the use of 1.7/1.8-style features in 1.6 code.
&gt;
&gt;With compatibility between 1.8 and 1.9 a key issue for ...<blockquote>
<p>When Ruby 1.8 was on the horizon and 1.6 was the normal version for people to use, someone created a library called "shim", which allowed the use of 1.7/1.8-style features in 1.6 code.</p>
<p>With compatibility between 1.8 and 1.9 a key issue for many people, such a "shim" library could be very useful.</p>
</blockquote>
<p>I would recommend you backports<br><a href="http://github.com/marcandre/backports">http://github.com/marcandre/backports</a></p>
<p>As it is pure Ruby, I believe you should still care where speed is important (though it would be better if users upgrade to 1.9 of course)</p>
<p>I found these "hacks" very bad to read, I would personally be tempted to use sth like backports instead (or maybe only a part of it)</p>Benoit DalozeThe 32nd Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-06-24:/comments/3822014-04-05T16:12:18ZYeah, blocks are no longer allowed to abuse variables like that (since they stick around after the iteration). You will need to switch to an explicit assignment, if that&#39;s what&#39;s really needed:
```ruby
@checklists.each do |checklist|
@chec...<p>Yeah, blocks are no longer allowed to abuse variables like that (since they stick around after the iteration). You will need to switch to an explicit assignment, if that's what's really needed:</p>
<div class="highlight highlight-ruby"><pre><span class="vi">@checklists</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">checklist</span><span class="o">|</span>
<span class="vi">@checklist</span> <span class="o">=</span> <span class="n">checklist</span>
<span class="c1"># ...</span>
<span class="k">end</span>
</pre></div>
<p>Hope that helps.</p>James Edward Gray IIThe 31st Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-06-23:/comments/3812014-04-05T16:12:18ZHi James,
I am now getting the following error
```
=============================================================
formal argument cannot be an instance variable
...@checklists.each do |@checklist|; @output_buffer.concat &quot;\r\...
... ...<p>Hi James,</p>
<p>I am now getting the following error</p>
<pre><code>=============================================================
formal argument cannot be an instance variable
...@checklists.each do |@checklist|; @output_buffer.concat "\r\...
... ^
Extracted source (around line #14):
11: &lt;%= sort_header_tag('last_modified_datetime',
:title =&gt; 'Last Modified') %&gt;
12: &lt;%= sort_header_tag('last_import_datetime',
:title =&gt; 'Last Import') %&gt;
13: &lt;th&gt;Resources&lt;/th&gt;
14: &lt;% @checklists.each do |@checklist|%&gt;
15: &lt;tr&gt;
16: &lt;td&gt;
17: &lt;%
==============================================================
</code></pre>
<p>Have you ever got this error. What could be the issue. </p>
<p>All these errors I am getting after migrating to Ruby 1.91</p>
<p>Thanks<br>
Chandu</p>ChandanThe 30th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-06-23:/comments/3802014-04-05T16:09:31ZIt was allowed in Ruby 1.8.6, though it did print a warning back then that it was deprecated.<p>It was allowed in Ruby 1.8.6, though it did print a warning back then that it was deprecated.</p>James Edward Gray IIThe 29th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-06-23:/comments/3792014-04-05T16:09:31ZI think, You are right. After removing spaces it looks good. It seems to be working.
But I am not sure how the same code was working with Ruby 1.8.6.
Thanks
Chandan<p>I think, You are right. After removing spaces it looks good. It seems to be working.</p>
<p>But I am not sure how the same code was working with Ruby 1.8.6.</p>
<p>Thanks<br>
Chandan</p>ChandanThe 28th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-06-23:/comments/3782014-04-05T16:09:31ZI&#39;m just guessing, but I believe the issue was that you had a space between the method name (`link_to`) and the opening parenthesis (`(`). Try taking out the space and I bet that fixes it up.<p>I'm just guessing, but I believe the issue was that you had a space between the method name (<code>link_to</code>) and the opening parenthesis (<code>(</code>). Try taking out the space and I bet that fixes it up.</p>James Edward Gray IIThe 27th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-06-23:/comments/3772014-04-05T16:09:31ZHi James,
I just upgraded from Ruby 1.8.6 to 1.9.1 and I found couple of issue while starting `script/server`.
1. Case stmt with `:` was throwing the error. I changed `:` to `then`, it worked
2. Just below the case stmt I had the below line...<p>Hi James,</p>
<p>I just upgraded from Ruby 1.8.6 to 1.9.1 and I found couple of issue while starting <code>script/server</code>.</p>
<ol>
<li>Case stmt with <code>:</code> was throwing the error. I changed <code>:</code> to <code>then</code>, it worked</li>
<li>Just below the case stmt I had the below line </li>
</ol><div class="highlight highlight-erb"><pre><span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="p">(</span> <span class="n">h</span><span class="p">(</span><span class="n">oval</span><span class="p">),</span> <span class="ss">:action</span> <span class="o">=&gt;</span> <span class="s1">'find_oval'</span><span class="p">,</span>
<span class="ss">:id</span> <span class="o">=&gt;</span> <span class="o">[</span><span class="vi">@sas_report_id</span><span class="p">,</span> <span class="n">new_oval</span> <span class="p">,</span> <span class="n">the_cve</span> <span class="o">].</span><span class="n">join</span><span class="p">(</span><span class="s2">"_"</span><span class="p">))</span><span class="cp">%&gt;</span><span class="x">&lt;br&gt;</span>
</pre></div>
<p>It thrown me the errors like </p>
<pre><code>-------------------------------------------------------------
/home/ton/vsweb/nvd/app/views/report/_sas_manual_show.rhtml:16:
syntax error, unexpected ',', expecting ')'
...( oval, :action =&gt; 'find_oval',:id =&gt; [@sas_report_id, new_o...
... ^
/home/ton/vsweb/nvd/app/views/report/_sas_manual_show.rhtml:16:
syntax error, unexpected ')', expecting keyword_end
...l , the_cve ].join("_"))).to_s); @output_buffer.concat "&lt;br&gt;...
---------------------------------------------------------
</code></pre>
<p>I then removed the opening and closing parentheses</p>
<div class="highlight highlight-erb"><pre><span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="n">h</span><span class="p">(</span><span class="n">oval</span><span class="p">),</span> <span class="ss">:action</span> <span class="o">=&gt;</span> <span class="s1">'find_oval'</span><span class="p">,</span>
<span class="ss">:id</span> <span class="o">=&gt;</span> <span class="o">[</span><span class="vi">@sas_report_id</span><span class="p">,</span> <span class="n">new_oval</span> <span class="p">,</span> <span class="n">the_cve</span> <span class="o">].</span><span class="n">join</span><span class="p">(</span><span class="s2">"_"</span><span class="p">)</span><span class="cp">%&gt;</span><span class="x">&lt;br&gt;</span>
</pre></div>
<p>It worked !!</p>
<p>Wondering what has got changed here in Ruby 1.9.1. </p>
<p>What else syntax changes are present in 1.9.1. I don't know which else places we need to change our code.</p>
<p>Anybody else got this error with 1.9.1. Have you got any solution. Please let me know. </p>
<p>Thanks<br>
Chandu</p>ChandanThe 26th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2010-05-13:/comments/3762014-04-05T16:01:23ZThe `:` for case statements was removed from Ruby syntax because `;` works in all versions and does not require special syntax.
```ruby
case x
when Hash ; puts &#39;a hash&#39;
```
I prefer it to `then`.<p>The <code>:</code> for case statements was removed from Ruby syntax because <code>;</code> works in all versions and does not require special syntax.</p>
<div class="highlight highlight-ruby"><pre><span class="k">case</span> <span class="n">x</span>
<span class="k">when</span> <span class="no">Hash</span> <span class="p">;</span> <span class="nb">puts</span> <span class="s1">'a hash'</span>
</pre></div>
<p>I prefer it to <code>then</code>.</p>Rein HenrichsThe 25th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2009-10-12:/comments/3312014-04-05T15:59:50ZThanks to Michael Barton. His fix is just what I sought.<p>Thanks to Michael Barton. His fix is just what I sought.</p>WilliamThe 24th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2009-09-22:/comments/3252014-04-05T15:59:50ZHi James,
Thanks for sharing. Based on your code I&#39;ve tried the following for backwards compatiblity with Ruby 1.8 where everything uses the `CSV` class constant.
```ruby
require &quot;csv&quot;
if CSV.const_defined? :Reader
# Ruby 1.8 compatible...<p>Hi James,</p>
<p>Thanks for sharing. Based on your code I've tried the following for backwards compatiblity with Ruby 1.8 where everything uses the <code>CSV</code> class constant.</p>
<div class="highlight highlight-ruby"><pre><span class="nb">require</span> <span class="s2">"csv"</span>
<span class="k">if</span> <span class="no">CSV</span><span class="o">.</span><span class="n">const_defined?</span> <span class="ss">:Reader</span>
<span class="c1"># Ruby 1.8 compatible</span>
<span class="nb">require</span> <span class="s1">'fastercsv'</span>
<span class="no">Object</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:remove_const</span><span class="p">,</span> <span class="ss">:CSV</span><span class="p">)</span>
<span class="no">CSV</span> <span class="o">=</span> <span class="no">FasterCSV</span>
<span class="k">else</span>
<span class="c1"># CSV is now FasterCSV in ruby 1.9</span>
<span class="k">end</span>
</pre></div>Michael BartonThe 23rd Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2009-02-02:/comments/2582014-04-05T15:57:38ZIt&#39;s actually the colon, not semicolon, that use to stand in for `then`. It was removed because it is being used in other ways, like the new `Hash` syntax.<p>It's actually the colon, not semicolon, that use to stand in for <code>then</code>. It was removed because it is being used in other ways, like the new <code>Hash</code> syntax.</p>James Edward Gray IIThe 22nd Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2009-02-02:/comments/2572014-04-05T15:57:38ZI thought the semi colon functioning as an alias for `then` was great, its easier to look read IMO<p>I thought the semi colon functioning as an alias for <code>then</code> was great, its easier to look read IMO</p>TJ HolowaychukThe 21st Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-14:/comments/1692014-04-05T16:14:36ZWhen Ruby 1.8 was on the horizon and 1.6 was the normal version for people to use, someone created a library called &quot;shim&quot;, which allowed the use of 1.7/1.8-style features in 1.6 code.
With compatibility between 1.8 and 1.9 a key issue for many...<p>When Ruby 1.8 was on the horizon and 1.6 was the normal version for people to use, someone created a library called "shim", which allowed the use of 1.7/1.8-style features in 1.6 code.</p>
<p>With compatibility between 1.8 and 1.9 a key issue for many people, such a "shim" library could be very useful.</p>Gavin SinclairThe 20th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-09:/comments/1682014-04-05T15:50:46ZYes, I was able to sway Matz and `Enumerable#zip()` has been &quot;repaired.&quot;
Opinions seem to differ on whether on not to use the bug tracker on Rubyforge or the Ruby Core mailing list. I believe the core team is trying to get more into the bug ta...<p>Yes, I was able to sway Matz and <code>Enumerable#zip()</code> has been "repaired."</p>
<p>Opinions seem to differ on whether on not to use the bug tracker on Rubyforge or the Ruby Core mailing list. I believe the core team is trying to get more into the bug tacker habit, so it's probably best to start there for most things. I find I have more success with topics that should be discussed, like the <code>Enumerable#zip()</code> issue, on Ruby Core though. For serious issues, I recommend putting it on in the bug tracker then drawing attention to it on Ruby Core.</p>James Edward Gray IIThe 19th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-09:/comments/1672014-04-05T15:50:46ZThe `zip` problems appear to be fixed with the January 8th version, it&#39;s still ~50% slower than 1.8, but that&#39;s manageable.
James, I saw you post about this on Ruby-CORE mailing list. Is this the way to go for posting bugs?
I&#39;m asking this bec...<p>The <code>zip</code> problems appear to be fixed with the January 8th version, it's still ~50% slower than 1.8, but that's manageable.</p>
<p>James, I saw you post about this on Ruby-CORE mailing list. Is this the way to go for posting bugs?<br>
I'm asking this because I discovered what I think is a rather serious bug and posted a bug report on Rubyforge about three weeks ago, but there is no reply to the report or any of my follow-ups, other than the bug getting assigned to Matz.</p>Sander LandThe 18th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-07:/comments/1632014-04-05T15:49:36ZJames
many apologies about such many typos, I was referring to `#each_char` **only**. Thanks for the hint with `jcode` and `instance_methods.include?`. I missed &lt;code&gt;jcode&lt;/code&gt;&#39;s functionality.
<p>James</p>
<p>many apologies about such many typos, I was referring to <code>#each_char</code> <strong>only</strong>. Thanks for the hint with <code>jcode</code> and <code>instance_methods.include?</code>. I missed <code>jcode</code>'s functionality.</p>Robert DoberThe 17th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-07:/comments/1622014-04-05T15:49:36ZRobert: I guess I am still a little confused about our discussion. You&#39;ve mentioned both `String#to_char()` and `String#each_char()` and your code checks for one but creates the other. `String#to_char()` isn&#39;t a method I&#39;m familiar with and I c...<p>Robert: I guess I am still a little confused about our discussion. You've mentioned both <code>String#to_char()</code> and <code>String#each_char()</code> and your code checks for one but creates the other. <code>String#to_char()</code> isn't a method I'm familiar with and I can't locate and documentation on it.</p>
<p>Just FYI, I believe your code also has a bug in it. Checks like <code>instance_methods.include?("some_str")</code> don't work as expected in Ruby 1.9. Those method names are now returned as <code>Symbol</code> objects so <code>include?()</code> will fail to match the <code>String</code>.</p>
<p>You can load <code>jcode</code> and <code>enumerator</code> and use <code>enum_for(:each_char)</code> to get an <code>Enumerable::Enumerator</code> in Ruby 1.8 or 1.9. I do now understand that we were discussing many methods instead of a specific example though, so that may not help.</p>James Edward Gray IIThe 16th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-07:/comments/1612014-04-05T15:46:20ZFrancisco Laguna, since symbols now respond to `#=~`, I don&#39;t think that change is necessary, unless I am missing something. It should be noted, though, that for some reason Ruby 1.9 now emits a warning about `undef`&#39;ing `object_id`, so you may wa...<p>Francisco Laguna, since symbols now respond to <code>#=~</code>, I don't think that change is necessary, unless I am missing something. It should be noted, though, that for some reason Ruby 1.9 now emits a warning about <code>undef</code>'ing <code>object_id</code>, so you may want to preserve it too.</p>Daniel LuzThe 15th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-06:/comments/1602014-04-05T15:49:36ZI see we are talking about two different things.
1. I wanted a guard against the ruby version for **lots** of definitions, not only `String#to_char`.
2. I cannot use Ruby&#39;s `String#to_char` because I need the 1.9 functionality of the returned ...<p>I see we are talking about two different things.</p>
<ol>
<li>I wanted a guard against the ruby version for <strong>lots</strong> of definitions, not only <code>String#to_char</code>.</li>
<li>I cannot use Ruby's <code>String#to_char</code> because I need the 1.9 functionality of the returned <code>Enumerator</code> in case it is called without a block.</li>
</ol><p>Maybe the idea to write version agnostic code was not really what you are after here, and you emphasis on 1.9, in that case I am a little bit OT, as usual...</p>Robert DoberThe 14th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-06:/comments/1592014-04-05T15:49:36ZWell, I hope that any `each_char()` implementation would give me the expected one character at a time.
My main point though was that I felt safer using the `each_char()` method that comes with Ruby 1.8 than building my own.<p>Well, I hope that any <code>each_char()</code> implementation would give me the expected one character at a time.</p>
<p>My main point though was that I felt safer using the <code>each_char()</code> method that comes with Ruby 1.8 than building my own.</p>James Edward Gray IIThe 13th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-06:/comments/1582014-04-05T15:49:36ZJames
Now for the idea of saying
```ruby
require &quot;jcode&quot; unless &quot;&quot;.respond_to?(:each_char)
```
This is an approach I have seen first in Javascript for Browser Quirks but after some thoughts I believe that it is a bad idea for libraries...<p>James</p>
<p>Now for the idea of saying</p>
<div class="highlight highlight-ruby"><pre><span class="nb">require</span> <span class="s2">"jcode"</span> <span class="k">unless</span> <span class="s2">""</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="ss">:each_char</span><span class="p">)</span>
</pre></div>
<p>This is an approach I have seen first in Javascript for Browser Quirks but after some thoughts I believe that it is a bad idea for libraries. What if a <code>require</code> before our <code>require</code> just added <code>each_char</code> to <code>String</code>? And that is not exactly far fetched an idea either. </p>
<p>For applications however it will work, unless you <code>require</code> third part libraries carelessly before the code above, this however can be debugged easily…</p>
<p>For libraries there would be no way to debug or even fix it in a general manner.</p>
<p>One could of course argue that someone could tamper with <code>RUBY_VERSION</code> too, but well we still have to let people kill themselves if they insist, sigh!</p>Robert DoberThe 12th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-06:/comments/1572014-04-05T15:49:36ZI would probable just do:
```ruby
require &quot;jcode&quot; unless &quot;&quot;.respond_to?(:each_char)
```
<p>I would probable just do:</p>
<div class="highlight highlight-ruby"><pre><span class="nb">require</span> <span class="s2">"jcode"</span> <span class="k">unless</span> <span class="s2">""</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="ss">:each_char</span><span class="p">)</span>
</pre></div>James Edward Gray IIThe 11th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-05:/comments/1562014-04-05T15:49:36ZJames I am just working on RQ#151 and I want my solution to be version agnostic, up to now the following was my idea:
Write the code in v1.9 and just require a file to upgrade 1.8 ruby just enough to run your code, such the require can go away ...<p>James I am just working on RQ#151 and I want my solution to be version agnostic, up to now the following was my idea:</p>
<p>Write the code in v1.9 and just require a file to upgrade 1.8 ruby just enough to run your code, such the require can go away one day, here is a very first shot:</p>
<div class="highlight highlight-ruby"><pre><span class="k">class</span> <span class="nc">String</span>
<span class="k">unless</span> <span class="nb">instance_methods</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span> <span class="s2">"to_char"</span> <span class="p">)</span> <span class="k">then</span>
<span class="nb">require</span> <span class="s2">"enumerator"</span>
<span class="k">def</span> <span class="nf">each_char</span> <span class="o">&amp;</span><span class="n">blk</span>
<span class="k">return</span> <span class="n">enum_for</span><span class="p">(</span><span class="ss">:each_byte</span><span class="p">)</span><span class="o">.</span><span class="n">map</span><span class="p">{</span> <span class="o">|</span><span class="n">b</span><span class="o">|</span> <span class="n">b</span><span class="o">.</span><span class="n">chr</span> <span class="p">}</span> <span class="k">unless</span> <span class="n">blk</span>
<span class="n">enum_for</span><span class="p">(</span><span class="ss">:each_byte</span><span class="p">)</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">b</span><span class="o">|</span> <span class="n">blk</span><span class="o">.</span><span class="n">call</span> <span class="n">b</span><span class="o">.</span><span class="n">chr</span> <span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre></div>
<p>of course it would be much better to wrap the whole include<br>
file into a version test, but that very test might be a tough one, the following is rather a bad example:</p>
<div class="highlight highlight-ruby"><pre><span class="k">begin</span>
<span class="s2">""</span><span class="o">.</span><span class="n">to_a</span>
<span class="k">def</span> <span class="nf">to_char</span><span class="o">.</span><span class="n">.</span><span class="o">.</span>
<span class="o">.</span><span class="n">.</span><span class="o">.</span>
<span class="k">end</span>
<span class="k">rescue</span>
<span class="kp">nil</span>
<span class="k">end</span>
</pre></div>
<p>Going for the Ruby version constant</p>
<div class="highlight highlight-ruby"><pre><span class="k">if</span> <span class="sr">/^1\.8/</span> <span class="o">===</span> <span class="no">RUBY_VERSION</span> <span class="k">then</span>
<span class="o">.</span><span class="n">.</span><span class="o">.</span>
<span class="k">end</span>
</pre></div>
<p>is probably a sound decision after all.</p>
<p>What do you think?</p>
<p>Cheers</p>Robert DoberThe 10th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-04:/comments/1552014-04-05T15:57:38ZIf you still prefer the single character single line notation you can just substitute the colon with a semi-colon
1.9:
```ruby
case sound
when /bamf/i; puts &#39;Nightcrawler&#39;
when /boff/i; puts &#39;Batman&#39;
end
```<p>If you still prefer the single character single line notation you can just substitute the colon with a semi-colon</p>
<p>1.9:</p>
<div class="highlight highlight-ruby"><pre><span class="k">case</span> <span class="n">sound</span>
<span class="k">when</span> <span class="sr">/bamf/i</span><span class="p">;</span> <span class="nb">puts</span> <span class="s1">'Nightcrawler'</span>
<span class="k">when</span> <span class="sr">/boff/i</span><span class="p">;</span> <span class="nb">puts</span> <span class="s1">'Batman'</span>
<span class="k">end</span>
</pre></div>Chris GaffneyThe 9th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-04:/comments/1542014-04-05T15:30:56Z&gt; But not in Ruby 1.9; now an explicit `then` statement must be used
Or you could just do what everyone else does, and put what happens `then` on a new line. Then, you won&#39;t need `then`, and your code is more consistent and readable.
I prefe...<blockquote>
<p>But not in Ruby 1.9; now an explicit <code>then</code> statement must be used</p>
</blockquote>
<p>Or you could just do what everyone else does, and put what happens <code>then</code> on a new line. Then, you won't need <code>then</code>, and your code is more consistent and readable.</p>
<p>I prefer this implementation. Allowing same-line <code>then</code> with a colon was bad style, IMO - as is the use of colons as meaningful operators in general.</p>hkThe 8th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-04:/comments/1532014-04-05T15:27:53ZFor extension writers, ruby1.9 has, incorrectly in my opinion, deprecated Ruby&#39;s `version.h` file.
This means it is not possible to know the ruby version easily and you now MUST write a Makefile of some sort to pass the proper defines or to che...<p>For extension writers, ruby1.9 has, incorrectly in my opinion, deprecated Ruby's <code>version.h</code> file.</p>
<p>This means it is not possible to know the ruby version easily and you now MUST write a Makefile of some sort to pass the proper defines or to check if your ruby supports some feature through some try-compile checks.</p>
<p>This probably ranks as one of the worst changes in ruby 1.9.</p>
<p>This obviously begs the question why this was done (as there's no benefit) and what should extension developers do if some function exists in both ruby1.8 and ruby1.9 but has different functionality (as some of the cases show here).</p>ggaThe 7th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-03:/comments/1522014-04-05T15:26:37ZUsing each or map on a result from `Enumerable#zip` is also extremely slow in 1.9. I discovered this when an application took twice as long in 1.9 as in 1.8. The innermost loop had a `zip_with()` call (`zip` -&gt; `map`) which caused this.
```ruby...<p>Using each or map on a result from <code>Enumerable#zip</code> is also extremely slow in 1.9. I discovered this when an application took twice as long in 1.9 as in 1.8. The innermost loop had a <code>zip_with()</code> call (<code>zip</code> -&gt; <code>map</code>) which caused this.</p>
<div class="highlight highlight-ruby"><pre><span class="nb">require</span> <span class="s1">'benchmark'</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">Array</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">25</span><span class="p">){</span><span class="nb">rand</span><span class="p">}</span>
<span class="no">Benchmark</span><span class="o">.</span><span class="n">bmbm</span><span class="p">{</span><span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="n">x</span><span class="o">.</span><span class="n">report</span><span class="p">(</span><span class="s2">"zip"</span><span class="p">){</span> <span class="mi">1_000_000</span><span class="o">.</span><span class="n">times</span> <span class="p">{</span> <span class="n">a</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">a</span><span class="p">)</span><span class="o">.</span><span class="n">map</span><span class="p">{}</span> <span class="p">}</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Results in 1.8.6</p>
<pre><code> user system total real
zip 16.170000 0.320000 16.490000 ( 16.576643)
</code></pre>
<p>Results in 1.9</p>
<pre><code> user system total real
zip 192.360000 1.430000 193.790000 (195.467429)
</code></pre>
<p>Using <code>to_a</code> gives the same results.</p>
<p>And this is with the slow 1.8.6 ubuntu/enable-pthread version vs an -O3/no-pthread compiled 1.9. On most code the 1.9 version is about four times as fast as the 1.8.6 version.</p>Sander LandThe 6th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-03:/comments/1512014-04-05T15:23:12ZYes, I do need to get `HighLine` working under 1.9. I&#39;ll try to get to that before too long now. Thanks for reminding me.<p>Yes, I do need to get <code>HighLine</code> working under 1.9. I'll try to get to that before too long now. Thanks for reminding me.</p>James Edward Gray IIThe 5th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-03:/comments/1502014-04-05T15:46:20ZI found what Frederick said is especially important for the typical `BlankSlate` type of class. What was in 1.8:
```ruby
class BlankSlate
instance_methods.each { |meth|
undef_method(meth) unless meth =~ /\A__/
}
...
end
```
...<p>I found what Frederick said is especially important for the typical <code>BlankSlate</code> type of class. What was in 1.8:</p>
<div class="highlight highlight-ruby"><pre><span class="k">class</span> <span class="nc">BlankSlate</span>
<span class="nb">instance_methods</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">meth</span><span class="o">|</span>
<span class="n">undef_method</span><span class="p">(</span><span class="n">meth</span><span class="p">)</span> <span class="k">unless</span> <span class="n">meth</span> <span class="o">=~</span> <span class="sr">/\A__/</span>
<span class="p">}</span>
<span class="o">.</span><span class="n">.</span><span class="o">.</span>
<span class="k">end</span>
</pre></div>
<p>becomes in 1.9 (for example):</p>
<div class="highlight highlight-ruby"><pre><span class="k">class</span> <span class="nc">BlankSlate</span>
<span class="nb">instance_methods</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">meth</span><span class="o">|</span>
<span class="n">undef_method</span><span class="p">(</span><span class="n">meth</span><span class="p">)</span> <span class="k">unless</span> <span class="n">meth</span><span class="o">.</span><span class="n">to_s</span> <span class="o">=~</span> <span class="sr">/\A__/</span>
<span class="p">}</span>
<span class="o">.</span><span class="n">.</span><span class="o">.</span>
<span class="k">end</span>
</pre></div>
<p>Other than that, I noticed that <code>Thread#critical</code> and <code>Thread#critical=</code> went away, but for those of us who want to explicitely schedule stuff, <code>Fiber</code>s are nicer anyway. </p>
<p><code>IO.getc</code> will return a <code>String</code> thats one character long instead of the ASCII value of the character itself.</p>
<p>1.8:</p>
<div class="highlight highlight-ruby"><pre><span class="no">STDIN</span><span class="o">.</span><span class="n">getc</span>
<span class="n">a</span>
<span class="o">=&gt;</span> <span class="mi">97</span>
</pre></div>
<p>1.9:</p>
<div class="highlight highlight-ruby"><pre><span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">002</span><span class="p">:</span><span class="mi">0</span><span class="o">&gt;</span> <span class="no">STDIN</span><span class="o">.</span><span class="n">getc</span>
<span class="n">a</span>
<span class="o">=&gt;</span> <span class="s2">"a"</span>
</pre></div>
<p>This also breaks the excellent <code>HighLine</code> lib. <em>hint hint</em> </p>Francisco LagunaThe 4th Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-03:/comments/1492014-04-05T15:46:20ZA bunch of methods like `instance_variables`, `constants`, etc… that used to return strings now return symbols.<p>A bunch of methods like <code>instance_variables</code>, <code>constants</code>, etc… that used to return strings now return symbols.</p>Frederick CheungThe 3rd Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-02:/comments/1482014-04-05T15:18:25ZJust to be clear the `then` keyword was also supported in Ruby 1.8 so using it for conditionals is fine for both versions.<p>Just to be clear the <code>then</code> keyword was also supported in Ruby 1.8 so using it for conditionals is fine for both versions.</p>James Edward Gray IIThe 2nd Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-02:/comments/1472014-04-05T16:01:23ZRuby 1.9 introduces an incompatible syntax change for conditional statements such as `if` and `case`/`when`. Previously a colon could be used as a shorthand for a `then` statement; this is perhaps most useful with multiple `when` statements on on...<p>Ruby 1.9 introduces an incompatible syntax change for conditional statements such as <code>if</code> and <code>case</code>/<code>when</code>. Previously a colon could be used as a shorthand for a <code>then</code> statement; this is perhaps most useful with multiple <code>when</code> statements on one line. </p>
<p>The following is legitimate Ruby in 1.8:</p>
<div class="highlight highlight-ruby"><pre><span class="k">case</span> <span class="n">x</span>
<span class="k">when</span> <span class="no">Regexp</span> <span class="p">:</span> <span class="nb">puts</span> <span class="s1">'a regex'</span>
<span class="k">when</span> <span class="no">Hash</span> <span class="p">:</span> <span class="nb">puts</span> <span class="s1">'a regex'</span>
<span class="k">when</span> <span class="no">Numeric</span> <span class="p">:</span> <span class="nb">puts</span> <span class="s1">'a number'</span>
<span class="k">when</span> <span class="nb">String</span> <span class="p">:</span> <span class="nb">puts</span> <span class="s1">'a string'</span>
<span class="k">end</span>
</pre></div>
<p>But not in Ruby 1.9; now an explicit <code>then</code> statement must be used:</p>
<div class="highlight highlight-ruby"><pre><span class="k">case</span> <span class="n">x</span>
<span class="k">when</span> <span class="no">Regexp</span> <span class="k">then</span> <span class="nb">puts</span> <span class="s1">'a regex'</span>
<span class="o">.</span><span class="n">.</span><span class="o">.</span>
</pre></div>Alex FentonThe 1st Comment on "Getting FasterCSV Ready for Ruby 1.9"tag:graysoftinc.com,2008-01-02:/comments/1462014-03-27T01:38:24Z[Porting REXML to Ruby 1.9](http://intertwingly.net/blog/2007/12/31/Porting-REXML-to-Ruby-1-9) overlaps slightly and covers some additional ground.<p><a href="http://intertwingly.net/blog/2007/12/31/Porting-REXML-to-Ruby-1-9">Porting REXML to Ruby 1.9</a> overlaps slightly and covers some additional ground.</p>Sam RubyGetting FasterCSV Ready for Ruby 1.9tag:graysoftinc.com,2008-01-02:/posts/422014-04-05T16:14:36ZI want to share some tips I learned converting code to run on Ruby 1.9.<p>The call came down from on high just before the Ruby 1.9 release: replace the standard <code>csv.rb</code> library with <code>faster_csv.rb</code>. With only hours to make the change it was a little harder than I expected. The <code>FasterCSV</code> code base was pretty vanilla Ruby, but it required more work than I would have guessed to get running on Ruby 1.9. Let me share a few of the tips I learned while doctoring the code in the hope that it will help others get their code ready for Ruby 1.9.</p>
<h4>Ruby's <code>String</code> Class Grows Up</h4>
<p>One of the biggest changes in Ruby 1.9 is the addition of m17n (multilingualization). This means that Ruby's Strings are now encoding aware and we must clarify in our code if we are working with bytes, characters, or lines.</p>
<p>This is a good change, but the odds are that most of us have lazily used the old way to our advantage in the past. If you've ever written code like:</p>
<div class="highlight highlight-ruby"><pre><span class="n">lines</span> <span class="o">=</span> <span class="n">str</span><span class="o">.</span><span class="n">to_a</span>
</pre></div>
<p>you have bad habits to break. I sure did. Under Ruby 1.9 that code would translate to:</p>
<div class="highlight highlight-ruby"><pre><span class="n">lines</span> <span class="o">=</span> <span class="n">str</span><span class="o">.</span><span class="n">lines</span><span class="o">.</span><span class="n">to_a</span>
</pre></div>
<p><code>String#lines()</code> returns an <code>Enumerable::Enumerator</code> by default (more on that shortly), so you need to add the <code>to_a()</code> call unless you are going to follow-up with other iteration methods.</p>
<p>Now, if you need the code to run on both 1.8 and 1.9, you will need one more trick. First, if you just need to iterate over the lines you can use <code>String#each_line()</code> which is present in both versions. For less basic iterations, I recommend:</p>
<div class="highlight highlight-ruby"><pre><span class="n">lines</span> <span class="o">=</span> <span class="n">str</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">str</span><span class="o">.</span><span class="n">respond_to?</span><span class="p">(</span><span class="ss">:lines</span><span class="p">)</span> <span class="p">?</span> <span class="ss">:lines</span> <span class="p">:</span> <span class="ss">:to_s</span><span class="p">)</span><span class="o">.</span><span class="n">to_a</span>
</pre></div>
<p>Here I just call <code>String#lines()</code> if it is available and a no-op <code>String#to_s()</code> when it's not. You can safely follow that with any <code>Enumerable</code> method and it will work in Ruby 1.8 and Ruby 1.9.</p>
<h4>
<code>Enumerable#zip()</code> Took a Beating</h4>
<p><em>[<strong>Update</strong>: Both of my complaints about <code>zip()</code> were eventually addressed. The 1.8 behavior has been restored.]</em></p>
<p>If you were a fan of <code>Enumerable#zip()</code> under Ruby 1.8, odds are good that it's going to surprise you under Ruby 1.9.</p>
<p>First, the standard <code>Enumerable::Enumerator</code> library has been moved into the core as we already saw with <code>String#lines()</code>. With this move the core iteration methods have been enhanced to return an <code>Enumerable::Enumerator</code>, if called without a block. This is generally a nice iterator chaining feature. For example, making the fictional but oft-requested <code>map_with_index()</code> is now as easy as:</p>
<div class="highlight highlight-ruby"><pre><span class="n">enum</span><span class="o">.</span><span class="n">each_with_index</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="err">…</span> <span class="p">}</span>
</pre></div>
<p><code>Enumerable#zip()</code> may be the exception though. It already had a meaningful return value when called without a block. That has been overridden by the new behavior though, so you will now get an <code>Enumerable::Enumerator</code> when you probably expected an <code>Array</code>. I've found that I now need to type the following to get what I usually want:</p>
<div class="highlight highlight-ruby"><pre><span class="n">enum</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">other_enum</span><span class="p">)</span><span class="o">.</span><span class="n">to_a</span>
</pre></div>
<p>It's hard to see that as an improvement, but the fact is that it gets worse. For some reason I can't justify, another change was made to <code>Enumerable#zip()</code>. Let's look at what happens with <code>Enumerable</code> objects of different sizes under Ruby 1.8:</p>
<div class="highlight highlight-ruby"><pre><span class="o">&gt;&gt;</span> <span class="n">short</span> <span class="o">=</span> <span class="o">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="o">]</span>
<span class="o">=&gt;</span> <span class="o">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="o">]</span>
<span class="o">&gt;&gt;</span> <span class="n">long</span> <span class="o">=</span> <span class="sx">%w[one two three four]</span>
<span class="o">=&gt;</span> <span class="o">[</span><span class="s2">"one"</span><span class="p">,</span> <span class="s2">"two"</span><span class="p">,</span> <span class="s2">"three"</span><span class="p">,</span> <span class="s2">"four"</span><span class="o">]</span>
<span class="o">&gt;&gt;</span> <span class="n">short</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">long</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="o">[[</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"one"</span><span class="o">]</span><span class="p">,</span> <span class="o">[</span><span class="mi">2</span><span class="p">,</span> <span class="s2">"two"</span><span class="o">]]</span>
<span class="o">&gt;&gt;</span> <span class="n">long</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">short</span><span class="p">)</span>
<span class="o">=&gt;</span> <span class="o">[[</span><span class="s2">"one"</span><span class="p">,</span> <span class="mi">1</span><span class="o">]</span><span class="p">,</span> <span class="o">[</span><span class="s2">"two"</span><span class="p">,</span> <span class="mi">2</span><span class="o">]</span><span class="p">,</span> <span class="o">[</span><span class="s2">"three"</span><span class="p">,</span> <span class="kp">nil</span><span class="o">]</span><span class="p">,</span> <span class="o">[</span><span class="s2">"four"</span><span class="p">,</span> <span class="kp">nil</span><span class="o">]]</span>
</pre></div>
<p>Note that the size of the result set is based on the size of the <code>Enumerable</code> that is used as the receiver for the <code>Enumerable#zip()</code> call. This works out well in practice, because you can always find the longer count if you need to preserve all of the data. If you want the shorter results, you can lead with the smaller set or filter out the <code>nil</code> objects. The choice is in your hands.</p>
<p>Unfortunately, Ruby 1.9 changes the rules:</p>
<div class="highlight highlight-ruby"><pre><span class="o">&gt;&gt;</span> <span class="n">short</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">long</span><span class="p">)</span><span class="o">.</span><span class="n">to_a</span>
<span class="o">=&gt;</span> <span class="o">[[</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"one"</span><span class="o">]</span><span class="p">,</span> <span class="o">[</span><span class="mi">2</span><span class="p">,</span> <span class="s2">"two"</span><span class="o">]]</span>
<span class="o">&gt;&gt;</span> <span class="n">long</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">short</span><span class="p">)</span><span class="o">.</span><span class="n">to_a</span>
<span class="o">=&gt;</span> <span class="o">[[</span><span class="s2">"one"</span><span class="p">,</span> <span class="mi">1</span><span class="o">]</span><span class="p">,</span> <span class="o">[</span><span class="s2">"two"</span><span class="p">,</span> <span class="mi">2</span><span class="o">]]</span>
</pre></div>
<p>As you can see, the shortest <code>Enumerable</code> now limits the results no matter where it occurs. The problem with this change is that it discards data and you have to go out of your way to save it. This new behavior is documented though, so I assume it's intentional.</p>
<p>What do you do if you want a safe 1.8 data preserving <code>Enumerable#zip()</code> that works on 1.8 and 1.9? About the best I can come up with is:</p>
<div class="highlight highlight-ruby"><pre><span class="nb">require</span> <span class="s2">"enumerator"</span>
<span class="n">zipped</span> <span class="o">=</span> <span class="n">long</span><span class="o">.</span><span class="n">enum_for</span><span class="p">(</span><span class="ss">:each_with_index</span><span class="p">)</span><span class="o">.</span>
<span class="n">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">e</span><span class="p">,</span> <span class="n">i</span><span class="o">|</span> <span class="o">[</span><span class="n">e</span><span class="p">,</span> <span class="n">short</span><span class="o">.</span><span class="n">to_a</span><span class="o">[</span><span class="n">i</span><span class="o">]]</span> <span class="p">}</span>
</pre></div>
<p>Obviously, I'm open to better ideas.</p>
<h4>
<code>FasterCSV</code> is the New <code>CSV</code>
</h4>
<p>I found the above incompatibilities by introducing a new one. <code>FasterCSV</code> has replaced the standard <code>CSV</code> class in the standard library. By replaced, I mean that it is now called <code>CSV</code>. This will cause code that used the old library problems.</p>
<p>The methods provided on the <code>CSV</code> object are similar, but the old <code>CSV</code> code used positional parameters where as the new library uses a <code>Hash</code> argument syntax (e.g., <code>row_sep: "\r\n"</code>). That's going to trip up any non-trivial usage.</p>
<p>The new library is feature rich and fully documented, so I don't expect anyone to have trouble getting their code working under 1.9. The problem will be writing code that works on both versions. For that, I recommend using code like the following to determined which library you are working with:</p>
<div class="highlight highlight-ruby"><pre><span class="nb">require</span> <span class="s2">"csv"</span>
<span class="k">if</span> <span class="no">CSV</span><span class="o">.</span><span class="n">const_defined?</span> <span class="ss">:Reader</span>
<span class="c1"># use old CSV code here…</span>
<span class="k">else</span>
<span class="c1"># use FasterCSV style code, but with CSV class, here…</span>
<span class="k">end</span>
</pre></div>
<p>Feel free to <a href="mailto:james@graysoftinc.com">email me</a> with any other <code>CSV</code> compatibility questions.</p>
<h4>This is Just a Start</h4>
<p>The above is a short list of issues I've run into a couple of times now. Please feel free to add your own observations about Ruby 1.9 compatibility in the comments below. Let's do our best to make this post a generally useful resource for all.</p>James Edward Gray II