Forum: Ruby Problem redefining String::to_s

Posted by Javier 12 (jvalencia)
on 2013-01-31 19:56
I've been checking String::to_s source code and found an issue.

A program like this will not work:

   class String
      def to_s
         "example"
      end
   end

   puts "Hi"

The output will be "Hi" and not "example".

This is due to C code, it checks if object is a String, and then print
it directly without calling "to_s" (it calls to_s on all other classes)

I wanted to override String::to_s to apply some color to my program
output (just to check some things) and I can't.

Is this a missing feature?

(i'm using ruby 1.8.7)
Posted by unknown (Guest)
on 2013-02-01 07:24
(Received via mailing list)
Am 31.01.2013 19:56, schrieb Javier 12:
>     puts "Hi"
>
> (i'm using ruby 1.8.7)
(why???)


The built-in classes behave sometimes differently than the classes
you define. That's neither a bug nor a feature.
Also, why should puts send to_s to a string? It *is* already a string.

There seems to be gems to colorize output, or maybe this helps:
http://stackoverflow.com/questions/1489183/coloriz....

   class String
     def red
       "\e[31m#{self}\e[0m"
     end
   end

   puts 'Red text'.red


Regards,
Marcus
Posted by Javier 12 (jvalencia)
on 2013-02-02 01:06
I'm using CentOS, it ships with that version but it's fine.

I wanted to "intercept" to_s so I can test some variations on my output 
but I found it's impossible since "puts" won't call String.to_s

That's a bit annoying because you expect all objects to behave the same 
way.
Posted by unknown (Guest)
on 2013-02-02 10:21
(Received via mailing list)
Am 02.02.2013 01:07, schrieb Javier 12:
> I'm using CentOS, it ships with that version but it's fine.
>
> I wanted to "intercept" to_s so I can test some variations on my output
> but I found it's impossible since "puts" won't call String.to_s
>
> That's a bit annoying because you expect all objects to behave the same
> way.

Well, you should not expect that.
Why should to_s be sent to an object that already *is* a string???

Maybe you need to change the behaviour of puts
(sounds a little scary to me)...
Posted by Carlo E. Prelz (Guest)
on 2013-02-02 10:39
(Received via mailing list)
Subject: Re: Problem redefining String::to_s
  Date: sab 02 feb 13 06:21:06 +0900

Quoting sto.mar@web.de (sto.mar@web.de):

> Why should to_s be sent to an object that already *is* a string???

The method exists, and it is useful when you code method that expect
various parameters, and convert them all to strings. It is not invoked
in string expansion (for reasons of optimization, I believe).

You can redefine to_s, and then explicitly invoke it, like

class String
  def to_s
    'another string'
  end
end

'test'.to_s

Carlo
Posted by Javier 12 (jvalencia)
on 2013-02-02 13:06
unknown wrote in post #1094871:

> Well, you should not expect that.
> Why should to_s be sent to an object that already *is* a string???
>
> Maybe you need to change the behaviour of puts
> (sounds a little scary to me)...

because you're told that puts will call to_s in the object you try to 
print, and it's expected that all objects work the same way, that's all

it was an interesting find, and I have to rely on a custom String class 
because of that
Posted by unknown (Guest)
on 2013-02-02 15:54
(Received via mailing list)
Am 02.02.2013 13:06, schrieb Javier 12:
> unknown wrote in post #1094871:
>
>> Well, you should not expect that.
>> Why should to_s be sent to an object that already *is* a string???

>
> because you're told that puts will call to_s in the object you try to
> print, and it's expected that all objects work the same way, that's all

The docs tell differently:

ri IO.puts

Writes the given objects to ios as with IO#print.
[...]

ri IO.print

Writes the given object(s) to ios. The stream must be opened for
writing. If the output field separator ($,) is not nil, it will
be inserted between each object. If the output record separator
($\) is not nil, it will be appended to the output. If no arguments
are given, prints $_. *Objects that aren't strings* will be converted
by calling their to_s method.
[...]
Posted by unknown (Guest)
on 2013-02-02 16:01
(Received via mailing list)
Am 02.02.2013 13:06, schrieb Javier 12:
>
> it was an interesting find, and I have to rely on a custom String class
> because of that
>

Maybe you should describe your actual use case in more detail.

Couldn't you simply use a wrapper method that does the
coloring and puts to stdout?

Like:

   def colored_puts(string)
     puts "\e[31m#{string}\e[0m"
   end

   colored_puts 'Hi!'
Posted by tamouse mailing lists (Guest)
on 2013-02-03 06:00
(Received via mailing list)
If you're seriously going to monkey-patch String, then try this instead:

class String
  def colourise(colour=nil)
    me = self.dup
    me.colourise!(colour)
  end
  def colourise!(colour=nil)
    return self unless colour
    # do some magic to make things look the way you want
    self
  end
end

then call:

puts "Hello, world!".colourise :green

(for example)


But really, instead of that, take a look at the formatador gem. Great
for colourising things already!!
Posted by Matthew Kerwin (mattyk)
on 2013-02-03 08:12
(Received via mailing list)
On 3 February 2013 01:00, <sto.mar@web.de> wrote:

> coloring and puts to stdout?
>
> Like:
>
>   def colored_puts(string)
>     puts "\e[31m#{string}\e[0m"
>   end
>
>   colored_puts 'Hi!'
>
>
Philosophically I'd argue that this is more correct anyway.  If your
intention is to change all Strings everywhere (stored in memory, written 
to
files, sent over the network, stored in databases, etc.) to include 
extra
bytes that correspond with ANSI/VT escape sequences then by all means
monkeypatch String and co.; but if your intention is just to inject 
those
bytes into _console output_, you should do the patching at the _console
output phase_, either by messing with the IO#print family of methods, or
adding the new #colored_puts method Marcus presented above.

Note, too, that it's not just puts/print that call #to_s; if String#to_s
added ANSI escapes, you'd have to have special logic to ensure they were
only added once, or things could get a bit ... out of hand.

When in doubt, look for a gem that already does what you want.  Many 
exist,
and some are even pretty good. ;)

--
  Matthew Kerwin, B.Sc (CompSci) (Hons)
  http://matthew.kerwin.net.au/
  ABN: 59-013-727-651

  "You'll never find a programming language that frees
  you from the burden of clarifying your ideas." - xkcd
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.