Forum: Ruby what's the rules re whether a Hash can use either a Symbol or String to reference the value???

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D5df9fcd7ef4c3c937435d7d6adeab2a?d=identicon&s=25 Greg Hauptmann (Guest)
on 2009-01-12 21:51
(Received via mailing list)
Hi,
Getting confused with Hashes a bit.  It seems sometimes I can use both a
Symbol or a String to get the value back, but other times the Symbol
doesn't
work.  Is there any rule re how to remember how Hash handles setting and
getting values uses Symbol / String?

e.g. hash_variable[:amount] versus hash_variable["amount"]

e.g. hash_var = {:amount => 10}, versus hash_var = {"amount" => 10)
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2009-01-12 22:02
(Received via mailing list)
On Mon, Jan 12, 2009 at 9:50 PM, Greg Hauptmann
<greg.hauptmann.ruby@gmail.com> wrote:
> Hi,
> Getting confused with Hashes a bit.  It seems sometimes I can use both a
> Symbol or a String to get the value back, but other times the Symbol doesn't
> work.  Is there any rule re how to remember how Hash handles setting and
> getting values uses Symbol / String?
>
> e.g. hash_variable[:amount] versus hash_variable["amount"]
>
> e.g. hash_var = {:amount => 10}, versus hash_var = {"amount" => 10)

In general, a hash uses eql? to know if a key matches the one you are
asking for.
So in general a Symbol and it's String counterpart are not the same
key in a hash.
There are different implementations that allow using Strings / Symbols
to refer to the same key.
Search for HashWithIndifferentAccess or something like that. I think
Rails uses something similar, IIRC.
Maybe your confusing comes from the different behaviour when you are
using Rails vs non-Rails?

Jesus.
C40020a47c6b625af6422b5b1302abaf?d=identicon&s=25 Stefano Crocco (crocco)
on 2009-01-12 22:04
(Received via mailing list)
Alle lunedì 12 gennaio 2009, Greg Hauptmann ha scritto:
> Hi,
> Getting confused with Hashes a bit.  It seems sometimes I can use both a
> Symbol or a String to get the value back, but other times the Symbol
> doesn't work.  Is there any rule re how to remember how Hash handles
> setting and getting values uses Symbol / String?
>
> e.g. hash_variable[:amount] versus hash_variable["amount"]
>
> e.g. hash_var = {:amount => 10}, versus hash_var = {"amount" => 10)

By itself, a hash distinguish between strings and symbols, so if an
entry is
stored under a string key, you'll only be able to retrieve it using a
string
key. If the entry has a symbol entry, then it can only be obtained using
a
symbol key:

h ={'a' => 1, :b => 2}
puts h['a'] # => 1
puts h[:a]  # => nil
puts h[:b]  # => 2
puts h['b'] # => nil

You can setup the hash so that it will work either with strings or
symbols.
For example:

hash = Hash.new do |h, k|
  if k.is_a?(String) and h.has_key? k.to_sym then h[k] = h[k.to_sym]
  elsif k.is_a?(Symbol) and h.has_key? k.to_s then h[k] = h[k.to_s]
  else nil
  end
end

hash['a'] = 1
hash[:b] = 2
puts hash['a'] # => 1
puts hash[:a]  # => 1
puts hash[:b]  # => 2
puts hash['b'] # => 2
puts hash[1]   # => nil

See the documentation for Hash.new to see how passing it a block works.

I hope this helps

Stefano
245a6d22816ecaeac1c9080ad183b859?d=identicon&s=25 badboy (Guest)
on 2009-01-12 22:06
(Received via mailing list)
Greg Hauptmann schrieb:
>
first:
every time you call hash_var["amount"] a new string is created.
But if you call with :amount, :amount will always be the same object.

next:
the default Hash class does not mix String- and Symbol-Keys.
so
   hash_var[:amount] = 10
   hash_var["amount"] = 11
   hash_var[:amount] != hash_var["amount"] # => true

but for example ActiveSupport (used in Rails) defines a class
HashWithIndifferentAccess.
there all Symbol-keys gets converted to a String, so that either :amount
or "amount" point to the same entry.

So if you want to know how to handle it, ask the variable for its class
(if someone uses monkey-patching you will lose =P)
D5df9fcd7ef4c3c937435d7d6adeab2a?d=identicon&s=25 Greg Hauptmann (Guest)
on 2009-01-12 22:12
(Received via mailing list)
thanks guys - interesting question for the Rails guys is whether you
have to
explicitly ask for a HashWithIndifference,  i.e. just wondering whether
it's
possible in Rails to ask for a Hash but really get a monkey patched
HashWithIndiffrence back without it being obvious...
F53b05cdbdf561cfe141f69b421244f3?d=identicon&s=25 David A. Black (Guest)
on 2009-01-12 22:36
(Received via mailing list)
Hi --

On Tue, 13 Jan 2009, Greg Hauptmann wrote:

> thanks guys - interesting question for the Rails guys is whether you have to
> explicitly ask for a HashWithIndifference,  i.e. just wondering whether it's
> possible in Rails to ask for a Hash but really get a monkey patched
> HashWithIndiffrence back without it being obvious...

HashWithIndifferentAccess is just a subclass of Hash. I don't think it
can be described as monkey patched, though I'm never sure what that
term means. Some methods return instances of it; some return instances
of Hash.


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!
391f9b787cdc12aa2c179713f5103e3a?d=identicon&s=25 Ilan Berci (iberci)
on 2009-01-12 22:36
Greg Hauptmann wrote:
> thanks guys - interesting question for the Rails guys is whether you
> have to
> explicitly ask for a HashWithIndifference,  i.e. just wondering whether
> it's
> possible in Rails to ask for a Hash but really get a monkey patched
> HashWithIndiffrence back without it being obvious...

There is no guarantees of getting any "type" back from ANY method in
ruby..  with rails, you can just convert it to an one if you aren't
sure..

my_hash = HashWithIndifferentAccess.new(my_hash)


By the way, there is no monkey patching here.. HashWithIndifferentAccess
is it's own class.  To be considered monkey patching, the Hash class
itself would be modified to be used in an indifferent fashion..

ilan
D5df9fcd7ef4c3c937435d7d6adeab2a?d=identicon&s=25 Greg Hauptmann (Guest)
on 2009-01-12 23:31
(Received via mailing list)
agreed - slip on my part to use the term - what I meant to refer to was
"Some methods return instances of it; some return instances of Hash" -
as
Ilan pointed out, confirming that Rails can do this to you...
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-01-13 08:26
(Received via mailing list)
On 12.01.2009 22:02, Stefano Crocco wrote:
>
>
> You can setup the hash so that it will work either with strings or symbols.
> For example:
>
> hash = Hash.new do |h, k|
>   if k.is_a?(String) and h.has_key? k.to_sym then h[k] = h[k.to_sym]
>   elsif k.is_a?(Symbol) and h.has_key? k.to_s then h[k] = h[k.to_s]
>   else nil
>   end
> end

IMHO there is a downside to assign to the hash in the block because that
changes the Hash.  This would not work with a frozen Hash for example.

I'd probably rather adjust keys on insertion and retrieval, e.g. always
change them to Symbols.

Kind regards

  robert
This topic is locked and can not be replied to.