[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

PHP-like Array/Hash creation in Ruby

Jan Reitz

10/11/2006 11:37:00 AM

I used PHP for a long time, a little bit C# and recently started to
learn about Ruby.
I do like Ruby very much from the first looks
It has "my_array.sort" like in c#, not that ugly (imo) "sort($myarray)"
And it has q'n'd qualitys like php for example: definition at first
assignment, no need for interfaces and so on.

But! one thing i really miss from PHP just writing :
$my_array[4][5] = "moep"; (no initialize before)
this does not work in ruby, i had to
my_array = Array.new(16) { Array.new 16 }
first.
and if the array wasn't great enough i end up with element 16 (the
17th) complaining:
NoMethodError: undefined method `[]=' for nil:NilClass
(this only occurs at "my_array[16][5] = 1",
not at "my_array[4][16] = 1")

hm, so i thought, if NilClass has no []= method, why dont i define it,
(i read very often that this is rubys great adv. over most languages
out there, that u can extend even the basic classes), so it becomes an
array in that place... but that included "self = Array.new" which
caused another complaint: "Can't change the value of self"

I read alot of topics about cant change value of self, and i think that
i have a different problem than these discussed before.
i dont want to 1.next! => 2 so please dont tell me that i can't do
that, i know that, and i know its junk
i want just:
hans = nil (or even omit this line)
hans[1] = "test"
or
my_array = Array.new(16) { Array.new 16 }
my_array[16][1] = 1
not:
nil[1] = "test"

I hope my English was well enough to be understood.

- Jan Reitz

11 Answers

Jules

10/11/2006 12:07:00 PM

0

Could you post some real php code that uses this feature? It isn't a
problem if you code it right. Instead of:

a = nil
a[12] = "something"

You can just do:

a = []
a[12] = "something"

and instead of:

a = nil
a[12][0] = "foo"
a[12][1] = "bar"
a[12][2] = "baz"

You use:

a = []
a[12] = ["foo", "bar", "baz"]

Jan Reitz wrote:
> I used PHP for a long time, a little bit C# and recently started to
> learn about Ruby.
> I do like Ruby very much from the first looks
> It has "my_array.sort" like in c#, not that ugly (imo) "sort($myarray)"
> And it has q'n'd qualitys like php for example: definition at first
> assignment, no need for interfaces and so on.
>
> But! one thing i really miss from PHP just writing :
> $my_array[4][5] = "moep"; (no initialize before)
> this does not work in ruby, i had to
> my_array = Array.new(16) { Array.new 16 }
> first.
> and if the array wasn't great enough i end up with element 16 (the
> 17th) complaining:
> NoMethodError: undefined method `[]=' for nil:NilClass
> (this only occurs at "my_array[16][5] = 1",
> not at "my_array[4][16] = 1")
>
> hm, so i thought, if NilClass has no []= method, why dont i define it,
> (i read very often that this is rubys great adv. over most languages
> out there, that u can extend even the basic classes), so it becomes an
> array in that place... but that included "self = Array.new" which
> caused another complaint: "Can't change the value of self"
>
> I read alot of topics about cant change value of self, and i think that
> i have a different problem than these discussed before.
> i dont want to 1.next! => 2 so please dont tell me that i can't do
> that, i know that, and i know its junk
> i want just:
> hans = nil (or even omit this line)
> hans[1] = "test"
> or
> my_array = Array.new(16) { Array.new 16 }
> my_array[16][1] = 1
> not:
> nil[1] = "test"
>
> I hope my English was well enough to be understood.
>
> - Jan Reitz

Jan Reitz

10/11/2006 1:17:00 PM

0

single dimension arrays are simple, because i just need that "a = []",
thats true and not much additional work. and they grow for themselves
too even if i initialize them with eg. Array.new(16).
all great.

but the autogrowing is limited to the last dimension.
in a[x][y] the y will grow when i assign something to them, the x too
but it would contain nil instead if "Array", thats because the a[x]
dimension is a "Array of Objects" and not an "Array of Arrays", the
a[x] does not know that autoresizes should spawn new "Array"s in the
newly generated spaces.

i dont have constant size of elements that could be added in just one
constant line, i have data comming in from DB's, files and network.

take 3-dimensional (points in space) data that i read from a file and i
want to store them in a 3 dimensional array.

without autogrowing i have to read the file completely and get the mins
and maxs and have an array created with this dimensions, then i read
the file again (ok i could have stored it, but i have to go over it
again) and put the contents in the array
OR
file.each { |x,y,z,data|
a[x] = [] if a[x].nil ?
a[x][y] = [] if a[x][y].nil ?
a[x][y][z] = data
}
OR
file.each { |x,y,z,data|
a[x][y][z] = data
}

method 2 might look ok, but why not have it easier with method 3?
the a = [] is a shortcut.
the h = {} too.
why not have another shortcut if its technically possible ?

you could even determine if the key is not a fixnum and create a Hash
instead

in php the Arrays are Hashes too (i dont know if all the Arrays are
Hashes).
we (at my company) sometimes use them like xml, meaning no common size
(how great can x be) and depth ([x][y][z][n...]) among the elements.

machines['VP21']['status'] = 'running'
machines['VP21']['rotation_speed'] = 210
machines['VP21']['workers'] = ['Peter','Paul','Mary']

or better
machines['VP21'][:status] = :running
machines['VP21'][:rotation_speed] = 210
machines['VP21'][:workers] = ['Peter','Paul','Mary']


and no, i dont need this to be a class, that would double/tripple my
work, because 'VP22' has nothing that rotates....

Jules wrote:
> Could you post some real php code that uses this feature? It isn't a
> problem if you code it right. Instead of:
>
> a = nil
> a[12] = "something"
>
> You can just do:
>
> a = []
> a[12] = "something"
>
> and instead of:
>
> a = nil
> a[12][0] = "foo"
> a[12][1] = "bar"
> a[12][2] = "baz"
>
> You use:
>
> a = []
> a[12] = ["foo", "bar", "baz"]
>
> Jan Reitz wrote:
> > I used PHP for a long time, a little bit C# and recently started to
> > learn about Ruby.
> > I do like Ruby very much from the first looks
> > It has "my_array.sort" like in c#, not that ugly (imo) "sort($myarray)"
> > And it has q'n'd qualitys like php for example: definition at first
> > assignment, no need for interfaces and so on.
> >
> > But! one thing i really miss from PHP just writing :
> > $my_array[4][5] = "moep"; (no initialize before)
> > this does not work in ruby, i had to
> > my_array = Array.new(16) { Array.new 16 }
> > first.
> > and if the array wasn't great enough i end up with element 16 (the
> > 17th) complaining:
> > NoMethodError: undefined method `[]=' for nil:NilClass
> > (this only occurs at "my_array[16][5] = 1",
> > not at "my_array[4][16] = 1")
> >
> > hm, so i thought, if NilClass has no []= method, why dont i define it,
> > (i read very often that this is rubys great adv. over most languages
> > out there, that u can extend even the basic classes), so it becomes an
> > array in that place... but that included "self = Array.new" which
> > caused another complaint: "Can't change the value of self"
> >
> > I read alot of topics about cant change value of self, and i think that
> > i have a different problem than these discussed before.
> > i dont want to 1.next! => 2 so please dont tell me that i can't do
> > that, i know that, and i know its junk
> > i want just:
> > hans = nil (or even omit this line)
> > hans[1] = "test"
> > or
> > my_array = Array.new(16) { Array.new 16 }
> > my_array[16][1] = 1
> > not:
> > nil[1] = "test"
> >
> > I hope my English was well enough to be understood.
> >
> > - Jan Reitz

Logan Capaldo

10/11/2006 2:18:00 PM

0

On Wed, Oct 11, 2006 at 08:40:06PM +0900, Jan Reitz wrote:
> I used PHP for a long time, a little bit C# and recently started to
> learn about Ruby.
> I do like Ruby very much from the first looks
> It has "my_array.sort" like in c#, not that ugly (imo) "sort($myarray)"
> And it has q'n'd qualitys like php for example: definition at first
> assignment, no need for interfaces and so on.
>
> But! one thing i really miss from PHP just writing :
> $my_array[4][5] = "moep"; (no initialize before)
> this does not work in ruby, i had to
> my_array = Array.new(16) { Array.new 16 }
> first.
> and if the array wasn't great enough i end up with element 16 (the
> 17th) complaining:
> NoMethodError: undefined method `[]=' for nil:NilClass
> (this only occurs at "my_array[16][5] = 1",
> not at "my_array[4][16] = 1")
>
Yes, because since you can define [] for anything, ruby has no way of
"guessing" what kind of container you want like PHP does.
> hm, so i thought, if NilClass has no []= method, why dont i define it,
> (i read very often that this is rubys great adv. over most languages
> out there, that u can extend even the basic classes), so it becomes an
> array in that place... but that included "self = Array.new" which
> caused another complaint: "Can't change the value of self"
defining []= for nil is probably not a good idea. What I would suggest
you do is create your own container that has the semantics you want, if
you want to go down the route of writing additional code.
>
> I read alot of topics about cant change value of self, and i think that
> i have a different problem than these discussed before.
> i dont want to 1.next! => 2 so please dont tell me that i can't do
> that, i know that, and i know its junk
> i want just:
> hans = nil (or even omit this line)
> hans[1] = "test"
Like I said previously, since anything can have a [] method, ruby can't
determine that you wanted an array.
> or
> my_array = Array.new(16) { Array.new 16 }
> my_array[16][1] = 1
> not:
> nil[1] = "test"
>
> I hope my English was well enough to be understood.
Try this:

a = Hash.new { |hash, key| hash[key] = [] }
a[16][1] = "Whee"

or like I said, create your own container. (Creating your own may also
give you a better understanding of why the choices made in ruby are what
they are).

Ara.T.Howard

10/11/2006 3:05:00 PM

0

Jan Reitz

10/11/2006 3:15:00 PM

0


Logan Capaldo wrote:
> Yes, because since you can define [] for anything, ruby has no way of
> "guessing" what kind of container you want like PHP does.

i know that not only an array can have [], strings can have them too in
php, but for ease of use someone defined that if you use [] on an
undefinded variable it would become an array not a string, and since
noone uses []= on NilClass atm it could be used, to do just that in
ruby.
i don't ask "why not?", because most ruby users are not used to it and
wouldnt want it, but i do. i started to dislike php more and more, but
not because i can write $ary[1] = 'hans'; but because phps oo sucks
compared to ruby, the part with the $ary[1] = 'hans'; is better there.

you use the "a = []" shortcut too, its a shortcut by definition, it
says "make an Array", not a string, or something else that supports [].
just Array.new

> defining []= for nil is probably not a good idea. What I would suggest
> you do is create your own container that has the semantics you want, if
> you want to go down the route of writing additional code.

i just want an array, nothing more
ary = nil
ary[1] = 'moep'
ary.class
=> Array

OR

ary = Array.new(16) { Array.new 16 }
ary[99][99] = 'moep'
ary[99].class
=> Array

with a little typechecking on the parameter inside the brackets you
could even:

moep[:test_symbol] = "hans"
moep.class
=> Hash

moep2["string as key"] = "hans"
moep2.class
=> Hash

my problem is that if i have an multi dimensional array, and it needs
to grow (by itself if i assign values outside of the allocated space),
the newly created will be "nil" so i cant use my own class for that.

in c# 2.0 i would write
List<List<string>> mda = new List<List<string>>()
mda[99][99] = "test";

Tada, tested it and it does _not_ work, lol.....

BUT what hinders ruby to be better than that....

the question i ask is is it doable ?
can someone help solving ?
im stuck with this "cant reassign self" or whatever it said.

Ara.T.Howard

10/11/2006 4:11:00 PM

0

Jan Reitz

10/11/2006 5:06:00 PM

0

thanks for your insights response ara.
i did my last post before reading your first...

the Alib::OrderedAutoHash looks very nice and is one of the things that
i searched.

i think i allways used sparse arrays|hashes before, with some little
exceptions while programming in C#....

your example with 2**128 showed me that php uses sparse arrays/hashes
because when i was using something like $serial_number[7099144]='blah'
i would have instantly beaten the allowed ram limit.

i think i became a little savaged while using php (hope this is proper
english)
maybe i can still be saved, i'm programming a board game (carcasonne)
in gtk to learn ruby.

back on track about auto-re-initialization of nil (or empty variable is
better, i think) to Hash (forget about Array) i found that the nils all
have the same id, so by changing one of them to an Array i would turn
them all.
i dont want something like this powerfull "become" from smalltalk some
other ppl talked about, it can (infact must) get a new id, and does not
need to retain its interior (whats in nil that i wanted to retain)

anyone having an idea of how to do this ?

Ara.T.Howard

10/11/2006 7:00:00 PM

0

Logan Capaldo

10/12/2006 1:48:00 AM

0

On Thu, Oct 12, 2006 at 12:20:10AM +0900, Jan Reitz wrote:
>
> Logan Capaldo wrote:
> > Yes, because since you can define [] for anything, ruby has no way of
> > "guessing" what kind of container you want like PHP does.
>
> i know that not only an array can have [], strings can have them too in
> php, but for ease of use someone defined that if you use [] on an
> undefinded variable it would become an array not a string, and since
> noone uses []= on NilClass atm it could be used, to do just that in
> ruby.
> i don't ask "why not?", because most ruby users are not used to it and
> wouldnt want it, but i do. i started to dislike php more and more, but
> not because i can write $ary[1] = 'hans'; but because phps oo sucks
> compared to ruby, the part with the $ary[1] = 'hans'; is better there.
>
In PHP $ary[1] = 'hans' must be an array. I can't create something else
that supports the same syntax.

In Ruby, ary[1] = 'hans' could be an array, could be a hash, could be a
string, could be any user created class. It could also mask errors,
Like for instance:
b = 7
b[3] = 2
Should 'b' now magically be turned into [nil, nil, nil, 2] ? (I don't
know, I don't think so, but maybe it should).

When asking for magic, you must always consider the impact it will have
on the rest of the language and the rest of the programs out there.
> you use the "a = []" shortcut too, its a shortcut by definition, it
> says "make an Array", not a string, or something else that supports [].
> just Array.new
>
Ahh, but [] is different from []. ;) Rather, when I say a = [] it has
nothing to do with a[i] but rather it's writing an array literal (like
PHP's array()).
[1,2,3] would be the same as array(1,2,3) in PHP
[1,2] would be the same as array(1,2) in PHP
[1] would be the same as array(1) in PHP
and [] is the same as array() in PHP.
It's just an (un?)happy coincidence that it looks the same as the index
operator.
> > defining []= for nil is probably not a good idea. What I would suggest
> > you do is create your own container that has the semantics you want, if
> > you want to go down the route of writing additional code.
>
> i just want an array, nothing more
> ary = nil
> ary[1] = 'moep'
> ary.class
> => Array
>
> OR
>
> ary = Array.new(16) { Array.new 16 }
> ary[99][99] = 'moep'
> ary[99].class
> => Array
>
> with a little typechecking on the parameter inside the brackets you
> could even:
>
> moep[:test_symbol] = "hans"
> moep.class
> => Hash
>
> moep2["string as key"] = "hans"
> moep2.class
> => Hash
>
> my problem is that if i have an multi dimensional array, and it needs
> to grow (by itself if i assign values outside of the allocated space),
> the newly created will be "nil" so i cant use my own class for that.
>
It doesn't have to be, that's why you write your own class.
> in c# 2.0 i would write
> List<List<string>> mda = new List<List<string>>()
> mda[99][99] = "test";
>
> Tada, tested it and it does _not_ work, lol.....
>
> BUT what hinders ruby to be better than that....
>
Better is a question of opinion in this case.
> the question i ask is is it doable ?
> can someone help solving ?
> im stuck with this "cant reassign self" or whatever it said.
>


Jan Reitz

10/12/2006 10:01:00 AM

0

i will take a look at this

Logan Capaldo wrote:
> In PHP $ary[1] = 'hans' must be an array. I can't create something else
> that supports the same syntax.
>
> In Ruby, ary[1] = 'hans' could be an array, could be a hash, could be a
> string, could be any user created class. It could also mask errors,
in ruby, ary[1] = 'hans' does not do a thing, it only complains that
nil has no []= method defined.
in php, where someone has defined that using []= on a undefined
variable would result in the creation of an (sparse) array, he could
have defined that it would result in creation of a string, but he
didnt.

> Like for instance:
> b = 7
> b[3] = 2
> Should 'b' now magically be turned into [nil, nil, nil, 2] ? (I don't
> know, I don't think so, but maybe it should).

no, that would mean that i overloaded the []= method in Fixnum, but im
only talking about NilClass...
the [] at Fixnum shows you the value of the bit at this position, maybe
it makes sense to have a []= as a bit setter/unsetter, but its not in
there, i dont mind, i dont care, i dont want to define it.

> When asking for magic, you must always consider the impact it will have
> on the rest of the language and the rest of the programs out there.

like said before im not overloading it for anything but nil, and
everybody that uses []= on nil now gets errors, and most likely
"repairs" his code.

> Ahh, but [] is different from []. ;) Rather, when I say a = [] it has
> nothing to do with a[i] but rather it's writing an array literal (like
> PHP's array()).
> [1,2,3] would be the same as array(1,2,3) in PHP
> [1,2] would be the same as array(1,2) in PHP
> [1] would be the same as array(1) in PHP
> and [] is the same as array() in PHP.
> It's just an (un?)happy coincidence that it looks the same as the index
> operator.

i know its different, and in my opinion its a happy "coincidence", if
it was coincidence at all, using "§§" for example would not be so
inuitive for "shortcut array creation".

> > my problem is that if i have an multi dimensional array, and it needs
> > to grow (by itself if i assign values outside of the allocated space),
> > the newly created will be "nil" so i cant use my own class for that.
> >
> It doesn't have to be, that's why you write your own class.

i already see the light, in php i dont think that something like this
OrderedAutoHash would be possible to implement by the "user" because
the [] is a language construct there and a method call here.