When working with a record that has various fields represented using a
hash, do you prefer strings or symbols? Why?
With strings, it’s like this:
person = {
:name => "John Doe",
:age => 20
}
With symbols, it’s like this:
person = {
'name' => "John Doe",
'age' => 20
}
Symbols are one character shorter to type (:name v.s. ‘name’). But,
then I have to convert between symbols and strings sometimes using
String#intern or Symbol#id2name. I do a lot of CGI programming; if a
script like this is called:
add_person.rhtml?name=John%20Doe;age=20
then the “name” and “age” are given to me as strings, so I have to
call String#intern in order to convert them into symbols first.
When working with a record that has various fields represented using a
hash, do you prefer strings or symbols? Why?
With strings, it’s like this:
person = {
:name => "John Doe",
:age => 20
}
With symbols, it’s like this:
person = {
'name' => "John Doe",
'age' => 20
}
Your examples are the wrong way around!
Symbols are one character shorter to type (:name v.s. ‘name’). But,
then I have to convert between symbols and strings sometimes using
String#intern or Symbol#id2name. I do a lot of CGI programming; if a
script like this is called:
add_person.rhtml?name=John%20Doe;age=20
then the “name” and “age” are given to me as strings, so I have to
call String#intern in order to convert them into symbols first.
Given all this, I would use Strings if I were you. For plain indices that
don’t really need to be interpreted outside the hash, I use symbols. I think
symbols are more efficient, too (but probably not if you’re converting them to
strings all the time).
When working with a record that has various fields represented using a
hash, do you prefer strings or symbols? Why?
person = {
:name => "John Doe",
:age => 20
}
I would probably use symbols, since it is the same few values used many
times.
But wouldn’t write code like the above. I would create a class “Person”
instead. Hashes with a fixed set of keys are almost screaming for you to
create a new class.
/Anders
···
–
A n d e r s B e n g t s s o n | ndrsbngtssn@yahoo.se
Stockholm, Sweden |
Gratis e-mail resten av livet på www.yahoo.se/mail
Busenkelt!
Given all this, I would use Strings if I were you. For plain indices that
don’t really need to be interpreted outside the hash, I use symbols. I think
symbols are more efficient, too (but probably not if you’re converting them to
strings all the time).
Or converting strings to symbols, if I understood the OP correctly
As I understand it, the potential gain in using symbols, is depending on
how the hash value is computed. Since a symbol is an internalized
string, it could potentially be quicker. I tried a quick and dirty
profiling test. Not surprising, using symbols are quicker than using
strings. Naturally stringifying a symbol or interning a string before
hash lookup is slower than either of the above. (Quite surprising to me,
they both appear to be approximately equal in time usage.)
So it is a matter of weighing how many times you guess you will be
looking up with symbols directly versus when you need to internalize a
string. If the script sets the variables from the CGI once (requiring an
intern to get symbol), but access it in the script elsewhere using
symbol a lot of times, symbols would be the way to go. (CGI
communication usually is slow as heck anyway, since you probably have a
user infront of a HTML form being the slowest link
require 'profile'
N = 10000
H = { :abba => ‘:A’, ‘abba’ => ‘A’ }
def time_strings
N.times do |i| H[‘abba’] end
end
def time_string_interned
N.times do |i| H[‘abba’.intern] end
end
def time_symbols
N.times do |i| H[:abba] end
end
def time_symbols_stringified
N.times do |i| H[:abba.to_s] end
end
But wouldn’t write code like the above. I would create a class
“Person” instead. Hashes with a fixed set of keys are almost
screaming for you to create a new class.
I’ve thought of doing that, but I found certain properties of the hash
to be convenient. For example, Hash#keys will tell me the name of all
the fields inside the hash. Then, if I have a “person” object as
defined above, storing it into SQL is pretty simple:
(code not tested, but should be more or less right)
def insert(table, hash)
Db.do “INSERT INTO #{table} SET #{
#{hash}.to_a.collect {
>key, value| “#{key} = #{Mysql.quote(value)}”
}.join(”, “)
}”
end
insert(‘person’, person)
When I do it with a class, there doesn’t seem to be a way to get a
list of all the attributes in the class. (Or is there? If there was a
good way, I think it would be better for me to use classes since then
I get all the other nice features of classes.)
But wouldn’t write code like the above. I would create a class
“Person” instead. Hashes with a fixed set of keys are almost
screaming for you to create a new class.
I’ve thought of doing that, but I found certain properties of the hash
to be convenient. For example, Hash#keys will tell me the name of all
the fields inside the hash. Then, if I have a “person” object as
defined above, storing it into SQL is pretty simple:
(code not tested, but should be more or less right)
def insert(table, hash)
Db.do “INSERT INTO #{table} SET #{
#{hash}.to_a.collect {
>key, value| “#{key} = #{Mysql.quote(value)}”
}.join(”, “)
}”
end
insert(‘person’, person)
You can get the names of all instance variables of an object with
obj.instance_variables, so you could write something similar to the
above.
If you have everything in a Person class you can also let that class
know about the table structure the instances are stored in, so the
objects can store themselves even.
/Anders
···
–
A n d e r s B e n g t s s o n | ndrsbngtssn@yahoo.se
Stockholm, Sweden |
Följ VM på nära håll på Yahoo!s officielle VM-sajt www.yahoo.se/vm2002
Håll dig ajour med nyheter och resultat, med vinnare och förlorare…
Give your class a to_hash method (maybe
from_hash also)
Use a Struct
Hal
···
----- Original Message -----
From: “Anders Bengtsson” ndrsbngtssn@yahoo.se
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, October 17, 2002 1:14 PM
Subject: Re: Hashes v.s. Classes (was Re: Strings or symbols?)
You can get the names of all instance variables of an object with
obj.instance_variables, so you could write something similar to the
above.
If you have everything in a Person class you can also let that class
know about the table structure the instances are stored in, so the
objects can store themselves even.