Symbols vs. strings

I got the impression that when a method expects a Hash containing
certain keys, I can generally specify the keys using either Symbol or
String objects. So I tried this.

h = {}
h[:foo] = 19
h['foo'] = 20

and was surprised to see that those are treated as distinct entries in the Hash.

So how is it that I can sometimes choose whether I want to specify a
given key as either a Symbol or a String?

For example, when using Tk and w represents some widget, I think I can
say either

w.pack(:side => 'top')

or

w.pack('side' => 'top')

···

--
R. Mark Volkmann
Partner, Object Computing, Inc.

That can e.g. be implemented like this:

def pack(arghash)
  arghash = arghash.inject({}) { | r, (k, v) | r[k.to_s] = v; r }
  side = arghash['side']
  ...
end

regards,

Brian

···

On 26/08/05, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:

I got the impression that when a method expects a Hash containing
certain keys, I can generally specify the keys using either Symbol or
String objects. So I tried this.

h = {}
h[:foo] = 19
h['foo'] = 20

and was surprised to see that those are treated as distinct entries in the Hash.

So how is it that I can sometimes choose whether I want to specify a
given key as either a Symbol or a String?

For example, when using Tk and w represents some widget, I think I can
say either

w.pack(:side => 'top')

or

w.pack('side' => 'top')

--
R. Mark Volkmann
Partner, Object Computing, Inc.

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

Hi --

I got the impression that when a method expects a Hash containing
certain keys, I can generally specify the keys using either Symbol or
String objects. So I tried this.

h = {}
h[:foo] = 19
h['foo'] = 20

and was surprised to see that those are treated as distinct entries
in the Hash.

So how is it that I can sometimes choose whether I want to specify a
given key as either a Symbol or a String?

You can hook into the and = methods. Here's one way:

module SSHash
   def =(k,v)
     super(k.to_s,v)
   end

   def (k)
     super(k.to_s)
   end
end

h = {}.extend(SSHash)

h[:a] = 1
h["b"] = 2
p h["a"] # 1
p h[:b] # 2

(Note that redefining and = does not affect other get/set methods,
like fetch.)

David

···

On Fri, 26 Aug 2005, Mark Volkmann wrote:

--
David A. Black
dblack@wobblini.net

Just to clarify, are you saying that ...

1) If I want my code that accepts a Hash parameter to allow keys to be
either Symbols or Strings, I need to use an approach like you showed
above.

2) Many existing Ruby classes do this.

···

On 8/26/05, Brian Schröder <ruby.brian@gmail.com> wrote:

On 26/08/05, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:
> I got the impression that when a method expects a Hash containing
> certain keys, I can generally specify the keys using either Symbol or
> String objects. So I tried this.
>
> h = {}
> h[:foo] = 19
> h['foo'] = 20
>
> and was surprised to see that those are treated as distinct entries in the Hash.
>
> So how is it that I can sometimes choose whether I want to specify a
> given key as either a Symbol or a String?
>
> For example, when using Tk and w represents some widget, I think I can
> say either
>
> w.pack(:side => 'top')
>
> or
>
> w.pack('side' => 'top')

That can e.g. be implemented like this:

def pack(arghash)
  arghash = arghash.inject({}) { | r, (k, v) | r[k.to_s] = v; r }
  side = arghash['side']
  ...
end

--
R. Mark Volkmann
Partner, Object Computing, Inc.

Rails makes use of
http://api.rubyonrails.org/classes/HashWithIndifferentAccess.html
I don't think it's very common.

···

On 8/26/05, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:

Just to clarify, are you saying that ...

1) If I want my code that accepts a Hash parameter to allow keys to be
either Symbols or Strings, I need to use an approach like you showed
above.

2) Many existing Ruby classes do this.

--
gavri

> > I got the impression that when a method expects a Hash containing
> > certain keys, I can generally specify the keys using either Symbol or
> > String objects. So I tried this.
> >
> > h = {}
> > h[:foo] = 19
> > h['foo'] = 20
> >
> > and was surprised to see that those are treated as distinct entries in the Hash.
> >
> > So how is it that I can sometimes choose whether I want to specify a
> > given key as either a Symbol or a String?
> >
> > For example, when using Tk and w represents some widget, I think I can
> > say either
> >
> > w.pack(:side => 'top')
> >
> > or
> >
> > w.pack('side' => 'top')

> That can e.g. be implemented like this:
>
> def pack(arghash)
> arghash = arghash.inject({}) { | r, (k, v) | r[k.to_s] = v; r }
> side = arghash['side']
> ...
> end

Just to clarify, are you saying that ...

1) If I want my code that accepts a Hash parameter to allow keys to be
either Symbols or Strings, I need to use an approach like you showed
above.

2) Many existing Ruby classes do this.

Yes, that is two times true. Hashes do not special-case for strings or
symbols. (Nearly) anything can go into a Hash as keys. Generally ruby
does not special case very often. Thats what makes it so nice to learn
and use.

regards,

Brian

···

On 26/08/05, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:

On 8/26/05, Brian Schröder <ruby.brian@gmail.com> wrote:
> On 26/08/05, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:

--
R. Mark Volkmann
Partner, Object Computing, Inc.

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/