David U. wrote in post #1146932:
Robert K. wrote in post #1146925:
This has two disadvantages:
- You always create a new Hash even if the element exists.
Definitely, however that was just a simplified example. Block form is a
bit less readable.
You need it to avoid unnecessary object creation. Whether the worry is
worthwhile is probably debatable. I generally try to avoid unnecessary
work.
- The empty Hash is not inserted into the Array which is what the OP
wants.
Where do you see in the OP a requirement for storing an empty Hash into
an array ?
He wrote in post #1146155:
But I am looking for a way to get an empty hash ( for
first time ), for any index access from array
?
Later he wrote in post #1146161:
I was actually looking for Hash#default=
(http://www.ruby-doc.org/core-2.1.1/Hash.html#metho…). Why
Array class don’t have any such method, like Hash class has ?
Hash#default=
is very useful although.
So he wanted the same behavior as can be achieved with
Hash#default_proc, i.e. on first access insert a new Hash that is then
returned ob subsequent accesses.
irb a.fetch(1){|i| a[i]={}}[:foo]=:bar
=> :bar
Your example doesn’t work as requested as it populates nil values for
all missing indexes.
Well, you suggested Array#fetch.
That makes it disadvantage #4 of
the approach. 
As you can see autovivified `nil’ is returned instead of an expected {},
ie. an empty hash.
Right. Good catch.
My advice for OP:
If you have sparse indexes i.e. large gaps between entries I’d just go
with Hash and use Hash#default_proc according to the usual pattern:
data = Hash.new {|h,k| h[k] = {}}
If you use all (or most of) the indexes you have to cook this yourself,
e.g.
data = []
class <<data
alias _get []
def
_get(i) or self[i] = {}
end
end
And in the intended usage scenario “false” and “nil” are no issues.
Btw. strictly speaking there is no reliable way to determine from an
Array whether an index has been set (as opposed to what Hash provides -
you can distinguish the case where a key was explicitly set to nil or
just the default value was returned). So there is no other way as to
resort to the current field value.
The only alternative for reliably detecting key absence is using the
index or Array#fetch. But then you must ensure that for every access
past the last index all new indexes are filled immediately which seems a
bit wasteful to me:
data = []
class <<data
def
fetch(i) do
for j in self.size…i
self[j] = l = {}
end
l
end
end
end
Kind regards
robert