On Aug 24, 2008, at 10:12 PM, Charles Turner wrote:
On Sun, 24 Aug 2008 20:08:48 -0500, James Gray wrote:
We need something that works in both places, so we need to check for the new 1.9 method lines and map() over it instead, if present. The code would be something like:
str.send(str.respond_to?(:lines) ? :lines, :to_s).map { … }
Hope that helps.
Hi James-
Thanks for your suggestion. The solution is a bit tricky, though. I think I have to test for String's support of :map in 1.8, because :each_line is supported in both 1.8 and 1.9.
In 1.8, you can do: a.map but in 1.9, I think you have to do: a.each_line.to_a.map
You didn't read my code very well. Please scroll up and have another look. :)
I didn't use each_line() because it is available in both versions. I used the new lines() method, added in 1.9:
$ ruby_dev -ve 'puts "one\ntwo".lines.map { |l| l.capitalize }' ruby 1.9.0 (2008-03-01 revision 15664) [i686-darwin9.2.0] One Two
The next trick is sending a symbol. It looks like in 1.8 you can say "a.send(:map)", but the equivalent "a.send(:each_line.to_a.map)" isn't a valid symbol reference in Ruby.
Those two pieces of code are not equivalent. In the first, you send() a Symbol message to the object. In the second, you are calling to_a() on a Symbol.
I promise that send() still works in Ruby 1.9:
$ ruby_dev -ve 'p "one".send(:capitalize)' ruby 1.9.0 (2008-03-01 revision 15664) [i686-darwin9.2.0] "One"
I rewrote your suggestion as:
a.respond_to?(:map) ? a.map : a.each_line.to_a.map do |line| print line end
which works for 1.9, but doesn't in 1.8, I think because of the conditional's relation the "do" block.
The reason it works in 1.9 is that the standard enumerator library was moved into the core. With this move came the enhancement that most iterators now return an Enumerable::Enumerator when called without a block. Thus, in 1.9, it is legal to call map() without a block as you do above. The same is not legal in 1.8.
Hope that answers some of your questions.
James Edward Gray II