Why do this Ruby object have both to_s and inspect methods that appear to do the same thing?

38,454

Solution 1

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.

Solution 2

inspect is a method that, by default, tells you the class name, the instance's object_id, and lists off the instance's instance variables.

print and puts are used, as you already know, to put the value of the object's to_s method to STDOUT. As indicated by Ruby's documentation, Object#to_s returns a string representing the object -- used for end-user readability.

print and puts are identical to each other except for puts automatically appends a newline, while print does not.

Solution 3

To compare with Python, to_s is like __str__ and inspect is like __repr__. to_s gives you a string, whereas inspect gives you the string representation of the object. You can use the latter to construct an object if you wish.

Solution 4

For anyone arriving here after starting out with Ruby Koans, a simple example of where to_s and inspect differ in output is this:

nil.to_s     # will yield an empty string, ie ""
nil.inspect  # will yield the string "nil"

Solution 5

Further, there is a to_str method on certain objects, which you would call when you need a String-like object, and not just a string representation. (Try in IRB: [1,2,3].to_str and it will fail, yet [1,2,3].to_s will not.) I feel I should mention this because I've been bitten by it before :)

Share:
38,454
prosseek
Author by

prosseek

A software engineer/programmer/researcher/professor who loves everything about software building. Programming Language: C/C++, D, Java/Groovy/Scala, C#, Objective-C, Python, Ruby, Lisp, Prolog, SQL, Smalltalk, Haskell, F#, OCaml, Erlang/Elixir, Forth, Rebol/Red Programming Tools and environments: Emacs, Eclipse, TextMate, JVM, .NET Programming Methodology: Refactoring, Design Patterns, Agile, eXtreme Computer Science: Algorithm, Compiler, Artificial Intelligence

Updated on July 08, 2022

Comments

  • prosseek
    prosseek almost 2 years

    Why do this Ruby object both a to_s and inspect methods that appear to do the same thing?

    The p method calls inspect and puts/print calls to_s for representing the object.

    If I run

    class Graph
      def initialize
        @nodeArray = Array.new
        @wireArray = Array.new
      end
      def to_s # called with print / puts
        "Graph : #{@nodeArray.size}"
      end
      def inspect # called with p
        "G"
      end
    end
    
    if __FILE__ == $0
      gr = Graph.new
      p gr
      print gr
      puts gr
    end
    

    I get

    G
    Graph : 0
    Graph : 0
    
    • Then, why does Ruby have two functions do the same thing? What is the difference between to_s and inspect?
    • And what's the difference between puts, print, and p?

    If I comment out the to_s or inspect function, I get as follows.

    #<Graph:0x100124b88>
    #<Graph:0x100124b88>
    
  • BreakPhreak
    BreakPhreak almost 13 years
    I am probably doing something wrong, but to me in IRB the outputs were the same: "[1, 2, 3]". On the other hand, nil.to_s and nil.inspect produced "" and "nil" respectively.
  • aug2uag
    aug2uag about 11 years
    same here, to_s and inspect return same output (as of March 2013)
  • cdunn2001
    cdunn2001 about 11 years
    [1,2,3].to_s => "123"; [1,2,3].inspect => "[1, 2, 3]". "#{...}" uses the former; p ... uses the latter.
  • Burhan Ali
    Burhan Ali about 11 years
    Using ruby 1.8.7 I get [1,2,3].to_s => "123". With ruby 2.0.0 I get [1,2,3].to_s => "[1, 2, 3]". So the given example is either true or not true depending on what version you are talking about.
  • Stephen
    Stephen over 10 years
    According to release docs, starting in 2.0.0 "Object#inspect does always return a string like #<ClassName:0x…> instead of delegating to #to_s. [#2152]", so the difference between to_s and inspect is probably clearer in IRB once you upgrade. See: ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released
  • wchargin
    wchargin over 10 years
    But in Python eval(repr(z)) == z should be True: how do you achieve this in Ruby?
  • Cam Jackson
    Cam Jackson about 10 years
    eval(repr(z)) == z is a myth. It's very rarely a useful thing to do, and has lots of potential problems. This article is a good start: stupidpythonideas.blogspot.com.au/2013/11/…
  • Cam Jackson
    Cam Jackson about 10 years
    Alex Martelli expresses the same sentiment here: stackoverflow.com/a/1436756/665488. It's just too hard to keep your __repr__s working like that, for very little real practical advantage.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com almost 10 years
    Weird, for Regexp on 2.1.1 it feels like the contrary: /a/.inspect gives /a/ which is human readable, but /a/.to_s gives (?-mix:a).
  • Radix
    Radix over 7 years
    Time.new.inspect isn't showing the class name and object_id, it rather prints "2016-11-10 13:05:45 +0530" (Time in string)
  • Pelle
    Pelle almost 7 years
    Not sure what you mean with a string-like object, but as far as I understood, to_s is meant for string representation and as such is used on interpolation, whereas to_str is meant for implicit conversions such as type coersion.
  • Yasushi Shoji
    Yasushi Shoji about 6 years
    Ruby 1.9 changed Array#to_s to be Array#inspect. stackoverflow.com/q/3960392
  • Pablo
    Pablo almost 5 years
    As of today, version 2.6.3, I get the same output for both.