defining to_s works oddly?

Discussion in 'Ruby' started by Martin Elzen, Jul 26, 2005.

  1. Martin Elzen

    Martin Elzen Guest

    Hi all. Am I the only one that finds it odd that if I define a to_s
    function for a class, that if I do:
    puts obj

    I won't get errors, but if I try something like:
    s = String.new
    s += obj

    I get a 'can not convert a <class type>' into String type error'...

    It's no prob to write obj.to_s, it's just I expected the first version to
    call to_s automatically...

    Martin

    PS for clarity, my complete error producing example is as follows:

    class Animal

    def initialize(name)
    fail "name is nil" if name.nil?

    @name = name
    end


    def to_s
    "#{@name}"
    end

    end



    c = Animal.new('Snoes')

    puts c

    puts "substituted in a string literal: #{c}"


    s = String.new
    s += c

    #puts s
    Martin Elzen, Jul 26, 2005
    #1
    1. Advertising

  2. Martin Elzen

    Brad Wilson Guest

    ------=_Part_2943_23479942.1122391429631
    Content-Type: text/plain; charset=ISO-8859-1
    Content-Transfer-Encoding: quoted-printable
    Content-Disposition: inline

    To make a rough guess? So that you can say 'this is my human readable=20
    version' (to_s) vs. 'this is how you convert me to a string' (to_str).

    On 7/26/05, Jacob Fugal <> wrote:
    >=20
    > On 7/26/05, James Edward Gray II <> wrote:
    > > For that, you need the duck typed version of the method, to_str()...

    >=20
    > I'm curious about that... why the two methods, to_s/to_str? I know
    > it's been discussed before, and I *think* I understood it then, but
    > I've since forgotten and there are probably others who haven't heard
    > the explanation before.
    >=20
    > Jacob Fugal
    >=20
    >=20



    --=20
    Brad Wilson
    http://www.dotnetdevs.com/
    http://www.agileprogrammer.com/dotnetguy/

    Peter: "Oh my god, Brian, there's a message in my Alphabits. It says,=20
    'Oooooo.' "
    Brian: "Peter, those are Cheerios."
    - Family Guy

    ------=_Part_2943_23479942.1122391429631--
    Brad Wilson, Jul 26, 2005
    #2
    1. Advertising

  3. Hi Martin,

    > Am I the only one that finds it odd that if I define a
    > to_s function for a class, that if I do
    >
    > puts obj
    >
    > I won't get errors, but if I try something like
    >
    > s =3D String.new
    > s +=3D obj
    >
    > I get a [TypeError]


    You're probably not the only one. The reason why =E2=80=98puts=E2=80=99
    converts its argument using =E2=80=98to_s=E2=80=99 but String#+ doesn't i=
    s
    far from obvious.

    > It's no prob to write obj.to_s, it's just I expected the
    > first version to call to_s automatically...


    As James Edward Gray II quoted Why saying, =E2=80=9Cto_str is an
    implicit cast, whereas to_s is an explicit cast,=E2=80=9D and you
    could probably redefine String#+ to perform the explicit
    cast instead of the implicit with no problems resulting.

    But I wouldn't do that. There is a significant difference
    between =E2=80=98"#{foo}"=E2=80=99 (or =E2=80=98puts foo=E2=80=99) and =E2=
    =80=98"bar" + foo=E2=80=99:
    The former *must* result in a string, whereas the latter
    could reasonably result in something other than a string.

    Consider these two expressions:

    "1" + 2 and 1 + "2"

    Current Ruby behavior is to reject both with type errors.
    See, Fixnum#+ implicitly casts its argument into a number,
    and String#+ implicitly casts its argument into a string,
    but neither argument can be implicitly casted that way.

    [Again, the term =E2=80=9Cimplicit cast=E2=80=9D is not an exact descript=
    ion
    of what happens, but rather a shorter way of saying =E2=80=9Cconvert
    if possible and fail otherwise.=E2=80=9D]

    You could make either method use an explicit cast instead of
    an implicit, but if you make both explicit you would be in
    the following weird situation:

    "1" + 2 #=3D> "12"

    1 + "2" #=3D> 3

    Assuming you agree that this asymmetry is unacceptable,
    the question is, which cast should take precedence?

    Perl avoids this ambiguity by letting "1" =3D=3D 1, so that

    "1" + 2 =3D=3D 1 + "2" =3D=3D "3" =3D=3D 3.

    Ruby avoids it by requiring an explicit cast:

    "1" + 2.to_s #=3D> "12"

    1.to_s + "2" #=3D> "12"

    1 + "2".to_i #=3D> 3

    "1".to_i + 2 #=3D> 3


    I know this message doesn't provide any solutions, but I
    hope it can help you accept Ruby's behavior as reasonable
    (something I consider very important for trust reasons).

    --=20
    Daniel Brockman <>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.
    Daniel Brockman, Jul 27, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Craig Buchanan

    parent child dropdownlists acting oddly

    Craig Buchanan, Jun 27, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    464
    Craig Buchanan
    Jun 27, 2003
  2. thechaosengine

    Oddly sized sized password textbox

    thechaosengine, Sep 15, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    580
    David Hearn
    Sep 15, 2005
  3. jodasi
    Replies:
    0
    Views:
    386
    jodasi
    Nov 28, 2005
  4. johny smith
    Replies:
    8
    Views:
    412
    Peter Koch Larsen
    Jul 2, 2004
  5. Suraj Kurapati
    Replies:
    5
    Views:
    106
    Ken Bloom
    Dec 5, 2006
Loading...

Share This Page