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)
on 2013-01-31 19:56
on 2013-02-01 07:24
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
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.
on 2013-02-02 10:21
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)...
on 2013-02-02 10:39
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
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
on 2013-02-02 15:54
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. [...]
on 2013-02-02 16:01
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!'
on 2013-02-03 06:00
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!!
on 2013-02-03 08:12
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
Log in with Google account | Log in with Yahoo account
No account? Register here.