5

This question is about formatting ruby's strings.

In Python, built-in data structures have a built-in to-string method, and so when a variable is printed, the string is conveniently formatted to be reflective of the data structure used. For example:

>>>$ python
Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
$>>> a = [1,2,3,4]
$>>> str(a)
'[1, 2, 3, 4]'
$>>> print a
[1, 2, 3, 4]
$>>> d = { "a":"a", "b":"b", 1:5 }
$>>> str(d)
"{'a': 'a', 1: 5, 'b': 'b'}"
$>>> print d
{'a': 'a', 1: 5, 'b': 'b'}
$>>> x = [1, 23, 4]
$>>> print x
[1, 23, 4]

notice that when i print a, the value is [1, 2, 3, 4]

However, in ruby, when i try to do the same things, i get this result:

>>>$ irb
irb(main):001:0> x = [1,23,4]
=> [1, 23, 4]
irb(main):002:0> x.to_s
=> "1234"
irb(main):003:0> puts x
1
23
4 
=> nil
irb(main):004:0> print x
1234=> nil
irb(main):005:0> h = { "a" => "a", 1 => 5, 'b'=>'b' } 
=> {"a"=>"a", "b"=>"b", 1=>5}
irb(main):006:0> print h 
aabb15=> nil
irb(main):007:0> h.to_s
=> "aabb15"
irb(main):008:0> puts h
aabb15
=> nil
irb(main):009:0>

As you can see, there is no formatting with the to_s method. Furthermore, there's a uniqueness problem if i call to_s on [1,2,3,4] and [1,23,4] and [1234] because the to_s clumps all elements together so they all end up being "1234". I know that i can try to emulate the python built-in to-string methods for every native data structure by overriding the to_s method ( "[" + a.join(",") + "]" #just for arrays), but i was wondering if there is a better alternative since hacking it would seem to break the convention-over-configuration concept.

So is there a ruby equivalent of python's built-in to-string method?

3 Answers 3

9
[1,23,4].inspect #=> "[1, 23, 4]"
p [1,23,4] # Same as  puts [1,23,4].inspect
Sign up to request clarification or add additional context in comments.

4 Comments

gotcha, that's closer to what i wanted. thanks. I read through the Array API but couldn't find a get-around still for this: ---------------------------------------------- irb(main):002:0> [ 1,2,3,4,'a',"b" ].inspect => "[1, 2, 3, 4, \"a\", \"b\"]" ---------------------------------------------------- it'd be nice to not see the backslashes. is this possible?
print [1,2,3,4,'a',"b"].inspect => [1,2,3,4,'a',"b"]
thanks Adam. But just out of curiosity, how would you retain the value of the nicely formatted string? when you called print, the return value is a nil, not the formatted string.
@dzt: Your confusion seems to be that irb displays string in escaped form. I.e. if you have a string containing a tab, irb will print "\t" instead of an actual tab. The string still contains a real tab though. So if you do mystring = [1,2,3,4,'a',"b"].inspect, then mystring will contain a b surrounded by quotes and no backslashes even if irb displays the quotes as \".
9

In Ruby, there are four methods that are typically available for getting a string representation of an object.

  1. #to_str: this is part of Ruby's standard type conversion protocols (similar to to_int, to_ary, to_float, …). It is used if and only if the object really actually is a string but for whatever reason is not an instance of the String class. It is extremely unusual. In fact, in the entire core library, there is only the no-op implementation in the String class itself.
  2. #to_s: this is also part of Ruby's standard type conversion protocols (similar to to_i, to_a, to_f, …). It is used if the object has some sort of sensible string representation. It does not actually need to be a string. Almost all objects should respond to this.
  3. Kernel#String(obj): this is also part of Ruby's standard type conversion protocols (similar to Kernel#Integer(obj), Kernel#Array(obj), Kernel#Float(obj), …). It is the same as obj.to_s.
  4. #inspect: it is supposed to return a human-readable description of the object for debugging purposes. In other words: it is for inspecting an object (duh).

There are three methods for printing objects:

  1. Kernel#print(obj, ...): prints all objs separated by $, and terminated by $\. If an obj is not a String, print will call obj.to_s first.
  2. Kernel#puts(obj, ...): is basically equivalent to $stdout.puts(obj, ...). It also prints the objs, but it typically separates them with newlines. However, it also has some special case behavior, in particular it treats arrays specially by printing each item on a new line.
  3. Kernel#p(obj, ...): similar to puts but calls #inspect on all objs.

In addition to those, there is also the pp (pretty print) library in the standard library which adds a Kernel#pp(obj, ...) method.

Then, there's the awesome_print library and hirb.

1 Comment

Thanks, this helps clear up a lot. Thanks for introducing Hirb too, this work great with viewing Rails's active record models.
0

Use inspect

irb(main):001:0> h = { "a" => "a", 1 => 5, 'b'=>'b' }
=> {"a"=>"a", "b"=>"b", 1=>5}
irb(main):003:0> puts h.inspect
{"a"=>"a", "b"=>"b", 1=>5}
=> nil
irb(main):004:0>

2 Comments

thanks. but is there a get-around for this:::: [ 1,2,3,4,'a',"b" ].inspect => "[1, 2, 3, 4, \"a\", \"b\"]" ------- as in is it possible to not see the backslashes?
Yes. As I show in my example, (in IRB), use puts h.inspect, not h.inspect

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.