Construct [*nil] works differently in 1.6 and 1.8

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.

Gennady Bystritksy schrieb:

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

"Gennady Bystritksy" <gfb@tonesoft.com> schrieb im Newsbeitrag news:41DF1E8F.7020404@tonesoft.com...

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.new.to_a

=> [#<Object:0x10188a10>]

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

ObjectSpace.each_object(Module){|cl| p cl if cl.instance_methods.include? "to_ary" }

Array
=> 365

Kind regards

    robert

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.

···

On Jan 7, 2005, at 10:32 PM, Pit Capitain wrote:

Gennady Bystritksy schrieb:

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

Pit Capitain <pit@capitain.de> writes:

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"]

This "feature" gives me the creeps.

Christian Neukirchen
<chneukirchen@gmail.com>

Christian Neukirchen schrieb:

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

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag news:m2pt0eeubv.fsf@lilith.local...

Pit Capitain <pit@capitain.de> writes:

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

"Robert Klemme" <bob.news@gmx.net> writes:

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag
news:m2pt0eeubv.fsf@lilith.local...

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"]

irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> [a]
=> [[1, 2, 3]]

:slight_smile:

Regards

    robert

Christian Neukirchen
<chneukirchen@gmail.com>

Pit Capitain <pit@capitain.de> writes:

Christian Neukirchen schrieb:

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 know.

                                                          I think you
have to define your own method. If you need an example, let me know.

Regards,
Pit

Thanks, I can do that on my own... it's just that I found this
behavior, albeit somehow logical, very confusing in the past.

Christian Neukirchen
<chneukirchen@gmail.com>

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag news:m2hdlqeb11.fsf@lilith.local...

"Robert Klemme" <bob.news@gmx.net> writes:

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag
news:m2pt0eeubv.fsf@lilith.local...

Hello,

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

  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

"Robert Klemme" <bob.news@gmx.net> writes:

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag
news:m2hdlqeb11.fsf@lilith.local...

"Robert Klemme" <bob.news@gmx.net> writes:

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag
news:m2pt0eeubv.fsf@lilith.local...

Hello,

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

  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

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

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

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.

Kind regards

    robert

Christian Neukirchen
<chneukirchen@gmail.com>

"Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag
news:m2d5wde75h.fsf@lilith.local...

"Robert Klemme" <bob.news@gmx.net> writes:

> "Christian Neukirchen" <chneukirchen@gmail.com> schrieb im Newsbeitrag
> news:m2hdlqeb11.fsf@lilith.local...
>> "Robert Klemme" <bob.news@gmx.net> writes:
>>
>>> "Christian Neukirchen" <chneukirchen@gmail.com> schrieb im

Newsbeitrag

>>> news:m2pt0eeubv.fsf@lilith.local...
>>>>
>>>> Hello,
>>>>
>>>> do you maybe also know a nice trick to make it a single-element

Array

>>>> iff it's not already an Array?
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Ooops, sorry, I overread that. Then of course my proposal is not a
> solution.
>
> Btw, for what do you need that? Just curious...

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?

def f(*a) p a end

=> nil

f( "aa\nb" )

["aa\nb"]
=> nil

f( "aab" )

["aab"]
=> nil

f( "aab", "bb" )

["aab", "bb"]
=> nil

f( 1,2,3 )

[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

"Robert Klemme" <bob.news@gmx.net> writes:

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

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?

def f(*a) p a end

=> nil

The splat operator works differently here.

f( "aa\nb" )

["aa\nb"]
=> nil

f( "aab" )

["aab"]
=> nil

f( "aab", "bb" )

["aab", "bb"]
=> nil

f( 1,2,3 )

[1, 2, 3]
=> nil

I usually had the arguments in an array that should be splatted.

···

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

--
Christian Neukirchen <chneukirchen@gmail.com> http://kronavita.de/chris/