Construct [*nil] works differently in 1.6 and 1.8

  • Thread starter Gennady Bystritksy
  • Start date
G

Gennady Bystritksy

Hi, rubyists

In ruby 1.6 I use the following quite often to quickly convert to arrays:

a = [ *o ]

If 'o' is already an array, 'a' will be the same. If 'o' is non-nil, 'a'
becomes an array with 'o' as a single element. Otherwise, if 'o' is nil,
'a' becomes an empty array. Nice and clean.

However, in 1.8 if 'o' is nil, 'a' becomes an array with a single
element nil.

In other words:
in 1.6 [ *nil ] -> []
in 1.8 [ *nil ] -> [ nil ]

Was this incompatibility introduced deliberately or is it a bug that
slipped through?

It becomes a problem (or rather inconvenience) in 1.8, as I cannot
replace [ *o ] with o.to_a as in 1.6, because ruby 1.8 gives warning
"default `to_a' will be obsolete" for instances of user defined classes.

Thanks in advance,
Gennady.
 
P

Pit Capitain

Gennady said:
In ruby 1.6 I use the following quite often to quickly convert to arrays:

a = [ *o ]

If 'o' is already an array, 'a' will be the same. If 'o' is non-nil, 'a'
becomes an array with 'o' as a single element. Otherwise, if 'o' is nil,
'a' becomes an empty array. Nice and clean.

However, in 1.8 if 'o' is nil, 'a' becomes an array with a single
element nil.

Hi Gennady,

you can use the method "Array":

p Array( [ 1, 2, 3, ] )
p Array( "x" )
p Array( nil )

results in

[1, 2, 3]
["x"]
[]

Regards,
Pit
 
G

Gennady Bystritsky

Hi, Pit

I have checked that Array(nil) works fine both in 1.6 and 1.8, thanks
for the tip. Nevertheless, [ *o ] feels so much more attractive ;-).
And I still do not see the reason for the behavior being changed. Is
there any?

Thank you very much,
Gennady.

Gennady said:
In ruby 1.6 I use the following quite often to quickly convert to
arrays:
a = [ *o ]
If 'o' is already an array, 'a' will be the same. If 'o' is non-nil,
'a' becomes an array with 'o' as a single element. Otherwise, if 'o'
is nil, 'a' becomes an empty array. Nice and clean.
However, in 1.8 if 'o' is nil, 'a' becomes an array with a single
element nil.

Hi Gennady,

you can use the method "Array":

p Array( [ 1, 2, 3, ] )
p Array( "x" )
p Array( nil )

results in

[1, 2, 3]
["x"]
[]

Regards,
Pit

Sincerely,
Gennady Bystritsky
 
R

Robert Klemme

Gennady Bystritksy said:
Hi, rubyists

In ruby 1.6 I use the following quite often to quickly convert to arrays:

a = [ *o ]

If 'o' is already an array, 'a' will be the same.

No, there will be two arrays containing the same references. Note the
difference:
foo=%w{a b c d} => ["a", "b", "c", "d"]
foo.id => 135018196
foo.to_a.id => 135018196
[*foo].id
=> 135018196

foo#to_a just returns self while [*foo] creates a new array.
If 'o' is non-nil, 'a' becomes an array with 'o' as a single element.
Otherwise, if 'o' is nil, 'a' becomes an empty array. Nice and clean.

However, in 1.8 if 'o' is nil, 'a' becomes an array with a single element
nil.

Which is more consistent IMHO.
In other words:
in 1.6 [ *nil ] -> []
in 1.8 [ *nil ] -> [ nil ]

Was this incompatibility introduced deliberately or is it a bug that
slipped through?

I'd say the 1.6 code is inconsistent and that was fixed in later versions.
It becomes a problem (or rather inconvenience) in 1.8, as I cannot replace
[ *o ] with o.to_a as in 1.6, because ruby 1.8 gives warning "default
`to_a' will be obsolete" for instances of user defined classes.

You can easily fix this by

class Object; def to_a; [self] end end
=> [#<Object:0x10188a10>]

Note also that there is #to_ary which should be implemented if a class has a
reasonable array representation:
Array
=> 365

Kind regards

robert
 
P

Pit Capitain

Christian said:
do you maybe also know a nice trick to make it a single-element Array
iff it's not already an Array?

irb(main):001:0> Array("foo\nbar")
=> ["foo\n", "bar"]

This "feature" gives me the creeps.

I didn't know this behavior before, but it is documented. I think you have to
define your own method. If you need an example, let me know.

Regards,
Pit
 
R

Robert Klemme

Christian Neukirchen said:
Pit Capitain said:
Hi Gennady,

you can use the method "Array":

p Array( [ 1, 2, 3, ] )
p Array( "x" )
p Array( nil )

results in

[1, 2, 3]
["x"]
[]

Regards,
Pit

Hello,

do you maybe also know a nice trick to make it a single-element Array
iff it's not already an Array?

irb(main):001:0> Array("foo\nbar")
=> ["foo\n", "bar"]
["foo\nbar"]
=> ["foo\nbar"]

Regards

robert
 
R

Robert Klemme

Christian Neukirchen said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Ooops, sorry, I overread that. Then of course my proposal is not a
solution.

Btw, for what do you need that? Just curious...

Kind regards

robert
 
R

Robert Klemme

Christian Neukirchen said:
I needed that rather often for convenience stuff (pass a single
argument or a whole array of them etc.).

Ah, I see. But for methods arguments it works quite good, doesn't it?
["aa\nb"]
=> nil["aab"]
=> nil["aab", "bb"]
=> nil[1, 2, 3]
=> nil
When I used [*ary] to do that, I had some "mysterious bugs" that only
appeared if the particular string had a newline in it... it really
took me some time to find those bugs.

I imagine...

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top