Ruby 1.9 Array.to_s behaves differently?
Yes, you're calling to_s
on an array of strings. In 1.8 that is equivalent to calling join
, in 1.9 it is equivalent to calling inspect
.
To get the behavior you want in both 1.8 and 1.9, call join
instead of to_s
.
Difference in `Array#to_s` in Ruby 1.8 and Ruby 1.9
Here's what is actually in Ruby source code:
1.8.7:
rb_ary_to_s(ary)
VALUE ary;
{
if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
return rb_ary_join(ary, rb_output_fs);
}
In other words, in 1.8.7, to_s
calls join
.
1.9.3:
rb_ary_inspect(VALUE ary)
{
if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
return rb_exec_recursive(inspect_ary, ary, 0);
}
VALUE
rb_ary_to_s(VALUE ary)
{
return rb_ary_inspect(ary);
}
In other words, in 1.9.3, to_s
delegates to inspect
.
Note: in future, if you're wondering about a difference you're observing between two versions, you can try taking a look at source code. Easy to pull down from here: https://github.com/ruby/ruby
Not everything is going to be easy to find in there of course, but if you search around for a bit you can often find good leads. In this case, array.c
has what you're looking for.
Then you can switch back and forth between versions by issuing git checkout ruby_1_8_7
and git checkout ruby_1_9_3
.
Getting custom .to_s working in arrays
Override inspect
class Custom
def inspect
'custom thing'
end
end
c1 = Custom.new
c2 = Custom.new
c3 = Custom.new
[c1,c2,c3].to_s # => "[custom thing, custom thing, custom thing]"
Not getting correct output from to_s
The examples work using ruby 1.8.7, which is getting a bit dated. Ruby 1.9.3 (the current version) changed the to_s
implementation for Arrays and Hashes.
EDIT: See Ruby 1.9 Array.to_s behaves differently?
Why do this Ruby object have both to_s and inspect methods that appear to do the same thing?
inspect
is used more for debugging and to_s
for end-user or display purposes.
For example, [1,2,3].to_s
and [1,2,3].inspect
produce different output.
times function's values changes outside the loop
An easy/simple way to do this I think is as below:
array = []
4.times do |e|
e = e + 1
array << e
end
p array.join(',')
output: "1,2,3,4"
The above will print all the items separated by a comma, also this might be helpful join docs
Ruby Array#puts not using overridden implementation?
From the Ruby Programming Language:
alt text http://ecx.images-amazon.com/images/I/41n-JSlBHkL._SL75_.jpg
Output streams are appendable, like strings and arrays are, and you can write values to them with the <<
operator. puts
is one of the most common output methods. It converts each of its arguments to a string, and writes each one to the stream. If the string does not already end with a newline character, it adds one. If any of the arguments to puts is an array, the array is recursively expanded, and each element is printed on its own line as if it were passed directly as an argument to puts. The print
method converts its arguments to strings, and outputs them to the stream. If the global field separator $
, has been changed from its default value of nil
, then that value is output between each of the arguments to print
. If the output record separator $/
has been changed from its default value of nil
, then that value is output after all arguments are printed.
As for design decisions, that I do not know.
Why does Ruby include? behave differently when nested within an if/end conditional?
Here's what's happening in each of these examples:
First Example
This example outputs 1. Your string includes a j or J.
regardless of the previous line. The my_string.include?
check is being ignored as it's not used in a comparison anywhere, so the second line is just a regular puts
.
Second Example
The second example is a little more interesting. ("j" or "J")
is syntax in Ruby which will output the first of the provided arguments which evaluates to true
. "j"
evaluates to true because it's not nil or false, so it becomes the argument of the second include?
method. include?
is case-sensitive, so it will return false
– the string Jack
does not include a lowercase j
.
You can try this out by running irb
and entering something like 1 or 2
or false and 1
; you'll see pretty quickly that the first true argument is returned (or false
if no arguments are true).
There's no good way to make this work as-is, other than updating the include?
check to use something like set intersections. An easier solution may be to downcase
the input before checking characters.
Avdi Grimm posted a good video on using and
and or
in Ruby.
Third Example
The third example is calling include?
twice on the string, and returning true when it hits the second call, hence the if statement being evaluated.
Update
papirtiger's answer got me thinking, so I did a bit of digging with Ripper using the following script:
require 'ripper'
require 'pp'
expression = <<-FOO
if true
puts 'Hello'
end
FOO
pp Ripper.sexp(expression)
Here's the result:
[:program,
[[:if,
[:var_ref, [:@kw, "true", [1, 3]]],
[[:command,
[:@ident, "puts", [2, 2]],
[:args_add_block,
[[:string_literal,
[:string_content, [:@tstring_content, "Hello", [2, 8]]]]],
false]]],
nil]]]
After updating the expression to the following:
expression = <<-FOO
if
true
puts 'Hello'
end
FOO
This was the new output:
[:program,
[[:if,
[:var_ref, [:@kw, "true", [2, 2]]],
[[:command,
[:@ident, "puts", [3, 2]],
[:args_add_block,
[[:string_literal,
[:string_content, [:@tstring_content, "Hello", [3, 8]]]]],
false]]],
nil]]]
It looks as though Ruby does indeed ignore any whitespace and evaluate the next expression. I don't have enough expertise to dig much deeper, but after trying a few more examples (such as throwing a dozen newlines in after an if
statement), I'm convinced.
Related Topics
How to Find Which Operating System My Ruby Program Is Running On
Pg::Error: Select Distinct, Order by Expressions Must Appear in Select List
Is There an Efficient Way to Perform Hundreds of Text Substitutions in Ruby
Installing Bootstrap 3 on Rails App
How to Solve Error "Missing 'Secret_Key_Base' For 'Production' Environment" (Rails 4.1)
When to Use Symbols Instead of Strings in Ruby
How to Replace Accented Latin Characters in Ruby
Ruby Multiline Block Without Do End
How to Update Ruby Version 2.0.0 to the Latest Version in MAC Osx Yosemite
What's the Difference Between a Proc and a Lambda in Ruby
Rails Update_Attributes Without Save
Need a Simple Explanation of the Inject Method
How to Solve "Ruby Installation Is Missing Psych" Error
Failed to Build Gem Native Extension (Installing Compass)
How to Convert an Array to a Hash in Ruby
How to Test If a String Is Basically an Integer in Quotes Using Ruby