I always get this error:
test.rb:5: undefined method `[]’ for #Hashhash:0x2bd2e30
(NoMethodError)
But when I try to code something in irb it works:
irb(main):006:0* dt = { 2 => {2 => “H”, 3 => “C”}}
=> {2=>{2=>“H”, 3=>“C”}}
irb(main):007:0> puts dt[2][2]
H
=> nil
| @dt = { 2 => {2 => “H”, 3 => “C”},
|
|But when I try to code something in irb it works:
|irb(main):006:0* dt = { 2 => {2 => “H”, 3 => “C”}}
|=> {2=>{2=>“H”, 3=>“C”}}
|irb(main):007:0> puts dt[2][2]
|H
|=> nil
|
|What am I doing wrong??
|
|Thanks in advance
First of all, what you get is not a syntax error (which would have
produced an
error message like: syntax error, …). The error you see is caused by
calling a method on an object for which it isn’t defined.
The problem is that when you call the new method of a class (in your
case,
Hashhash.new), you don’t get the value returned by initialize, but the
object
created by new. This means that ah doesn’t contain a hash, but a
Hashhash,
which doesn’t have a [] method.
You have several options on how to do what you want. Depending on what
exactly
you need, I think the easiest ones are:
define an [] method for the Hashhash class. This way, the code you
wrote
will work exactly as you meant. Defining such a method is easy. Inside
the
definition of the Hashhash class, do:
def @dt[key]
end
Calling this method will return the hash stored in @dt under key. Since
this
is a hash, you’ll be able to retrieve the value corresponding to the key
2
define a method for the Hashhash class which returns the instance
variable @dt and use that to access the elements. To define a method which only
returns
the value of an instance variable, you can use the attr_reader class
method:
class Hashhash
attr_reader :dt
def initialize
…
end
end
Then, you can write
ha = Hashhash.new
ha.dt[2][2]
Do not use the Hashhash class and use a simple hash of hashes:
As for the reason it works in irb… well, from what you show us, you
aren’t
using the same code you used in the script. At least, in this case dt
isn’t an
instance variable (since it doesn’t start with @).
You don’t need to return anything from initialize' because its return value is discarded and the invokingnew’ method always
returns the created object. Btw you don’t need to return anything
rom assigment methods `member=’ either.
I think I will implement an accessor to the hash, I come from a Perl
world and would build the hash in a seperate routine (to hide the
initialisation) that returns a reference to the hash.
Would it be possible to make Hashhash inherit from Hash (by using <
Hash) and be able to use the [][] operator immediately in a way?
I think I will implement an accessor to the hash, I come from a Perl
world and would build the hash in a seperate routine (to hide the
initialisation) that returns a reference to the hash.
If you create a new class then the constructor is just sufficient - you
do not need another method that hides away invocation of YourClass.new.
Would it be possible to make Hashhash inherit from Hash (by using <
Hash) and be able to use the [][] operator immediately in a way?
Actually, you do not need to create another class (see my earlier
example). For that it might make sense to create a method that returns
a new instance with the initialization I have shown.
If you lack explanation: the construct Hash.new {|h,k| …} creates a
new Hash instance with its default_proc set to the block you provide.
This block is invoked whenever there is a key miss. In my case I just
built it in a way as to create another Hash on the fly with the same
default_proc and stuff it in the other Hash. The default_proc
propagation ensures you can arbitrarily nest Hashes. Of course, you can
also do something like this if you know you just need one level of
nested Hashes
ha = Hash.new {|h,k| h[k] = {}}
Question is whether you want to bother to create a class for this. IMHO
this makes only sense if you want to put additional logic into it (e.g.
checking elements that are placed in the Hash).
Kind regards
robert
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.