A question on singleton methods

Hello,

I have a hash full of objects, like so:

a_hash = { :a => "alpha", :b => "beta" }

I don’t I need to define a singleton method for one of the items in
the class. I thought I could do:

def a_hash.fetch(:a).to_s
    "ALPHA"
end

But all this gets me is a big fat error:

t.rb:2: syntax error, unexpected tSYMBEG, expecting ')'
def a_hash.fetch(:a).to_s
                  ^

This is just a minimal example. In real life, the objects in the hash
have been generated programatically, so I don’t have variable
references for them – just the keys.

Is it possible that there is a way around this error? If not, is there
another way to do what I’m trying to do? I’m pretty new to this, so
apologies in advance if it is an obvious mistake.

Thank you,

Mike Leonard

Hi Mike,

On Sun, Mar 9, 2008 at 10:34 AM, mike leonard [email protected]
wrote:

def a_hash.fetch(:a).to_s
“ALPHA”
end

The problem here is that you can’t involve a method call/dispatch (or
two)
in the method definition. “a_hash.fetch(:a).to_s” has to make at least
one
method call (a_hash.fetch(:a)), and then one defines the method on the
resulting object. Method definitions don’t work this way (they need to
be
resolvable in the current context, I believe). But there’s a way to get
there:

a ={:a => “q”}
=> {:a=>“q”}
b = a[:a]
=> “q”
a[:a].object_id
=> -606856898
b.object_id
=> -606856898
def b.some_method
puts “Hi.”
end
=> nil
b.some_method
Hi.
=> nil
a[:a].some_method
Hi.
=> nil

By the by, I’m not sure redefining a String’s #to_s will have any
effect. It
sounds strange - perhaps you’re better off building a class for those
objects and defining to_s on that?

Cheers,
Arlen

On Sat, Mar 8, 2008 at 11:34 PM, mike leonard [email protected]
wrote:

    "ALPHA"

references for them – just the keys.

Is it possible that there is a way around this error? If not, is there
another way to do what I’m trying to do? I’m pretty new to this, so
apologies in advance if it is an obvious mistake.

Thank you,

Mike Leonard

You could try this:

a_hash = { :a => “alpha”, :b => “beta” }

def (a_hash[:a]).to_s
“ALPHA”
end

a_hash.each do |key, value|
puts “#{key} = #{value.to_s}”
end
END
a = ALPHA
b = beta

Regards,
Sean

On Sat, Mar 8, 2008 at 5:47 PM, Arlen C. [email protected] wrote:

On Sun, Mar 9, 2008 at 10:34 AM, mike leonard [email protected] wrote:

def a_hash.fetch(:a).to_s
“ALPHA”
end

Congratulations Sean O’Halpin, you beat me to send button.

By the by, I’m not sure redefining a String’s #to_s will have any effect. It
sounds strange - perhaps you’re better off building a class for those
objects and defining to_s on that?

I have no idea what the possible purpose of redefining String#to_s is.
However, I think this brings to mind an interesting idea. As part of
Ruby’s duck typing initiative, many methods call to_str on objects
they expect to be strings. Having String#to_str return something other
than self could produce some extremely confusing results.

Daniel Brumbaugh K.

unsubscribe

By the by, I’m not sure redefining a String’s #to_s will have any effect. It
sounds strange - perhaps you’re better off building a class for those
objects and defining to_s on that?

Agreed. I’m really wanting to redefine #to_s for a String; it was just
the first method that I thought of when I was typing up a minimal
example of what I was trying to do. The important bit was the thing
with the singleton method. Many thanks for your help.

–Mike

On Mar 8, 9:26 pm, mike leonard [email protected] wrote:

By the by, I’m not sure redefining a String’s #to_s will have any effect. It
sounds strange - perhaps you’re better off building a class for those
objects and defining to_s on that?

Agreed. I’m really wanting to redefine #to_s for a String; it was just
the first method that I thought of when I was typing up a minimal
example of what I was trying to do. The important bit was the thing
with the singleton method. Many thanks for your help.

–Mike

Sorry, that should read I’m not really wanting to redefine #to_s for
a String.

mike leonard wrote:

Hello,

I have a hash full of objects, like so:

a_hash = { :a => "alpha", :b => "beta" }

I don’t I need to define a singleton method for one of the items in
the class. I thought I could do:

def a_hash.fetch(:a).to_s
    "ALPHA"
end

a_hash = { :a => “alpha”, :b => “beta” }

val = a_hash.fetch(:a)
puts val.class #String

$ri String#to_s

------------------------------------------------------------ String#to_s
str.to_s => str
str.to_str => str

 Returns the receiver.

And you don’t define methods like this:

def “sayhi”
puts ‘hi’
end

You define them like this:

def sayhi
puts ‘hi’
end

A method name is not a string.

mike leonard wrote:

def a_hash.fetch(:a).to_s
    "ALPHA"
end

This doesn’t work because ruby thinks you want to define a_hash.fetch
and is
then confused by the symbol in the parameter list. This however will
work:

def (a_hash.fetch(:a)).to_s
“ALPHA”
end

HTH,
Sebastian

On Mar 9, 4:29 am, Sebastian H. [email protected]
wrote:

end

HTH,
Sebastian

Jabber: [email protected]
ICQ: 205544826

That got it. Thanks to everyone who chimed in to clear that up for me.

Hi,

On Sun, Mar 9, 2008 at 3:39 PM, 7stud – [email protected] wrote:

A method name is not a string.

I think you’re a bit off the mark. He’s redefining an existing method
with a
new singleton one.

h = {:a => 1}
=> {:a=>1}
puts h.class
=> Hash

$ ri Hash#length
------------------------------------------------------------ Hash#length
hsh.length => fixnum
hsh.size => fixnum

Yet:

def h.length
puts “This works.”
end
=> nil

A method name is not a fixnum, either. He’s not trying to define a
method
called ‘alpha’, it was changing the definition of to_s.

Arlen