what's the rules re whether a Hash can use either a Symbol or Stringto reference the value???

G

Greg Hauptmann

[Note: parts of this message were removed to make it a legal post.]

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)
 
J

Jesús Gabriel y Galán

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.
 
S

Stefano Crocco

Alle luned=C3=AC 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 =3D {:amount =3D> 10}, versus hash_var =3D {"amount" =3D> 1=
0)

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

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

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

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

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

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

I hope this helps

Stefano
 
B

badboy

Greg said:
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)
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)
 
G

Greg Hauptmann

[Note: parts of this message were removed to make it a legal post.]

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

Greg Hauptmann schrieb:

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)


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)
 
D

David A. Black

Hi --

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!
 
I

Ilan Berci

Greg said:
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
 
G

Greg Hauptmann

[Note: parts of this message were removed to make it a legal post.]

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...
 
R

Robert Klemme

Alle lunedì 12 gennaio 2009, Greg Hauptmann ha scritto:
Hi,
Getting confused with Hashes a bit. It seems sometimes I can use botha
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

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top