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,

   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 Sun, Mar 9, 2008 at 10:34 AM, mike leonard <mikeleonard@gmail.com> wrote:

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 11:34 PM, mike leonard <mikeleonard@gmail.com> 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

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

unsubscribe

···

On Sat, Mar 8, 2008 at 6:34 PM, mike leonard <mikeleonard@gmail.com> 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

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

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.

--
Posted via http://www.ruby-forum.com/\.

mike leonard wrote:

def a\_hash\.fetch\(:a\)\.to\_s
    &quot;ALPHA&quot;
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

···

--
Jabber: sepp2k@jabber.org
ICQ: 205544826

> 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 Keeney

···

On Sat, Mar 8, 2008 at 5:47 PM, Arlen Cuss <celtic@sairyx.org> wrote:

On Sun, Mar 9, 2008 at 10:34 AM, mike leonard <mikeleonard@gmail.com> 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

Hi,

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

···

On Sun, Mar 9, 2008 at 3:39 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
------------------------------------------------------------------------

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

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

···

On Mar 9, 4:29 am, Sebastian Hungerecker <sep...@googlemail.com> wrote:

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
--
Jabber: sep...@jabber.org
ICQ: 205544826

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

···

On Mar 8, 9:26 pm, mike leonard <mikeleon...@gmail.com> 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