What method should a class provide for printf's %c format string?

Consider the following snippet:

···

---------------------------------------------

#!/usr/bin/ruby

class Thing
           
        def initialize(name)
                @name = name
        end
           
        def to_s
                @name
        end
           
        def to_i
                @name.length
        end
end

a = Bla.new("foo")

printf "%s\n", a
printf "%d\n", a
printf "%c\n", a

---------------------------------------------

This code breaks at the last line with the message :

./go7:22:in `printf': can't convert Thing into Integer (TypeError)

It seems that the printf conversion to %c tries to call a specific
method of my class to convert the object to the appropriate format. I am
a bit confused about the message "can't convert to integer", since the
to_i method is defined, and sucessfully called that the printf "%d"
line.

So, two questions arise

- what method am I supposed to provied for printf so it can handle the
  '%s' format string

- How can I figure this out myself. It seems that printf is trying to
  call something, but I have no way of telling exactly what it is
  trying to do. Is there some kind of tracing/debugging that can be
  switched on to see what's printf is trying to do ?

Thank you very much,

Gerald schrieb:

It seems that the printf conversion to %c tries to call a specific
method of my class to convert the object to the appropriate format. I am
a bit confused about the message "can't convert to integer", since the
to_i method is defined, and sucessfully called that the printf "%d"
line.

So, two questions arise

- what method am I supposed to provied for printf so it can handle the
  '%s' format string

- How can I figure this out myself. It seems that printf is trying to
  call something, but I have no way of telling exactly what it is
  trying to do. Is there some kind of tracing/debugging that can be
  switched on to see what's printf is trying to do ?

I guessed that it would try to implicitly convert the object to an Integer. Ruby usually uses to_int() for that. to_i() is used for explicit conversions.

I verified that guess by doing this:

irb(main):002:0> "%c" % Class.new { def to_int() ?A end }.new
=> "A"

Hope this helps.

···

--
http://flgr.0x42.net/

Yes, that was the solution, thank you very much. I must say it is a bit
confusing that the string and float methods are called to_s and to_f,
that to_i works for %d, but not for %c, and to_int works for both %d and
%c. Can you give me a referer to some official documentation describing
%these conversion functions ?

Thanks a lot,

···

Florian Gross <florgro@gmail.com> wrote:

Gerald schrieb:

It seems that the printf conversion to %c tries to call a specific
method of my class to convert the object to the appropriate format. I am
a bit confused about the message "can't convert to integer", since the
to_i method is defined, and sucessfully called that the printf "%d"
line.

So, two questions arise

- what method am I supposed to provied for printf so it can handle the
  '%s' format string

- How can I figure this out myself. It seems that printf is trying to
  call something, but I have no way of telling exactly what it is
  trying to do. Is there some kind of tracing/debugging that can be
  switched on to see what's printf is trying to do ?

I guessed that it would try to implicitly convert the object to an
Integer. Ruby usually uses to_int() for that. to_i() is used for
explicit conversions.

I verified that guess by doing this:

irb(main):002:0> "%c" % Class.new { def to_int() ?A end }.new
=> "A"

Hope this helps.

The rule for things like to_int, to_ary and to_str are basically if your object has a canonical representation as an integer it should support to to_int. If it can be represented as an integer in more than one way, e.g. ("10" is this a binary 2? a decimal 10? an octal 8?) you pick a representation and use to_i. The same rules follow for to_s vs. to_str and to_a vs. to_ary. What this also means is that unless your Thing is an _integer_ its likely "bad form" to implement to_int. But like most things in ruby this more a string suggestion than anything enforced by the language.

···

On Jul 29, 2006, at 6:15 AM, Gerald wrote:

Florian Gross <florgro@gmail.com> wrote:

Gerald schrieb:

It seems that the printf conversion to %c tries to call a specific
method of my class to convert the object to the appropriate format. I am
a bit confused about the message "can't convert to integer", since the
to_i method is defined, and sucessfully called that the printf "%d"
line.

So, two questions arise

- what method am I supposed to provied for printf so it can handle the
  '%s' format string

- How can I figure this out myself. It seems that printf is trying to
  call something, but I have no way of telling exactly what it is
  trying to do. Is there some kind of tracing/debugging that can be
  switched on to see what's printf is trying to do ?

I guessed that it would try to implicitly convert the object to an
Integer. Ruby usually uses to_int() for that. to_i() is used for
explicit conversions.

I verified that guess by doing this:

irb(main):002:0> "%c" % Class.new { def to_int() ?A end }.new
=> "A"

Hope this helps.

Yes, that was the solution, thank you very much. I must say it is a bit
confusing that the string and float methods are called to_s and to_f,
that to_i works for %d, but not for %c, and to_int works for both %d and
%c. Can you give me a referer to some official documentation describing
%these conversion functions ?

Thanks a lot,