Splat, #to_ary and #to_a

Hi!

I suppose this just qualifies as unexpected (by me) behaviour
but an odd thing happened when I wrote code like this:

[*“foo\nbar”] # => [“foo\n”, “bar”]

Mocking out the call sequence for the splat, it seems that
it first checks for #respond_to? :to_ary and, if so, sends
it to the object–the surprising part was that if it does
NOT respond to :to_ary, the splat simply calls #to_a on its
subject.

The idea behind the code, of course, is to have a single
expression that either constructs an Array or reproduces
the current one from whatever object we are dealing with.
This behaviour makes doing so a tad less concise :slight_smile:

Eero S. wrote:

Hi!

I suppose this just qualifies as unexpected (by me) behaviour
but an odd thing happened when I wrote code like this:

[*“foo\nbar”] # => [“foo\n”, “bar”]

On the same topic, this is a strange parsing:

stream.puts ([] << obj).join("\n")

Above is the same as writing:

stream.puts([] << obj).join("\n")

Hi,

In message “Re: Splat, #to_ary and #to_a
on Mon, 18 Sep 2006 11:12:43 +0900, Eero S.
[email protected] writes:

|I suppose this just qualifies as unexpected (by me) behaviour
|but an odd thing happened when I wrote code like this:
|
| [*“foo\nbar”] # => [“foo\n”, “bar”]

It’s fixed in 1.9. 1.8 will remain as it is now for the sake of
compatibility.

						matz.

Yukihiro M. wrote:

Hi,

In message “Re: Splat, #to_ary and #to_a
on Mon, 18 Sep 2006 11:12:43 +0900, Eero S.
[email protected] writes:

|I suppose this just qualifies as unexpected (by me) behaviour
|but an odd thing happened when I wrote code like this:
|
| [*“foo\nbar”] # => [“foo\n”, “bar”]

It’s fixed in 1.9. 1.8 will remain as it is now for the sake of
compatibility.

Thank you for clarification!

  					matz.

On 9/18/06, Eero S. [email protected] wrote:

NOT respond to :to_ary, the splat simply calls #to_a on its
subject.

The idea behind the code, of course, is to have a single
expression that either constructs an Array or reproduces
the current one from whatever object we are dealing with.
This behaviour makes doing so a tad less concise :slight_smile:

Can’t you just test whether the object is an Array (or if it supports
the array methods you need)?

x = “foo\nbar”
(x.is_a?(Array) ? x : [x]) # => [“foo\nbar”]
x = %w(a b c)
(x.is_a?(Array) ? x : [x]) # => [“a”, “b”, “c”]

On 9/17/06, Yukihiro M. [email protected] wrote:

It’s fixed in 1.9. 1.8 will remain as it is now for the sake of
compatibility.

Hmmmm,

Just what is the fix in 1.9.

Are you saying that
[*“foo\nbar”] #=> [“foo\nbar”]
in 1.9?

How about:
[*(1…4)]
which in 1.8.x produces [1, 2, 3, 4]

and which of these will change in 1.9?

def a(*arg)
p arg
end

a(“foo\nbar”)
which in 1.8.4 prints [“foo\nbar”]

a((1…3))
prints [1, 2, 3, 4]
a(1…3)
prints [1…3]

a(1…3, “foo\nbar”)
prints [1…3, “foo\nbar”]

a(*“foo\nbar”)
prints [“foo\n”, “bar”]

a(*(1…4))
prints [1, 2, 3, 4]

*a = “foo\nbar”
a gets [“foo\nbar”]
*a = (1…4)
a gets [1…4]
*a = “foo\nbar”, (1…3)
a gets [“foo\nbar”, 1…3]

I’m not sure that I see a consistent pattern here. But I have to say
that I think that the 1.8.x interpretations of

a(“foo\nbar”)
and
a(
(1…4))

both make sense since the caller is ASKING for the splat, and that
these two seem very similar to the
[*“foo\nbar”]
case which started this.

I’ve also always been surprised that String#to_a didn’t produce an
array of single character strings, instead of splitting the string
into lines, but that’s probably just a personal surprise, and I
wouldn’t expect that to change.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi,

In message “Re: Splat, #to_ary and #to_a
on Mon, 18 Sep 2006 12:28:18 +0900, “Rick DeNatale”
[email protected] writes:

|Just what is the fix in 1.9.
|
|Are you saying that
|[*“foo\nbar”] #=> [“foo\nbar”]
|in 1.9?

Yes. And if you are curious you can try it by yourself.

|How about:
|[*(1…4)]
|which in 1.8.x produces [1, 2, 3, 4]

Currently,

[1…4]

This may be an issue.

|and which of these will change in 1.9?
|
|def a(*arg)
| p arg
|end
|
|a(“foo\nbar”)
|which in 1.8.4 prints [“foo\nbar”]

[“foo\nbar”]

|a((1…3))
| prints [1, 2, 3, 4]

[1…3]

|a(1…3)
| prints [1…3]

[1…3]

|a(1…3, “foo\nbar”)
|prints [1…3, “foo\nbar”]

[1…3, “foo\nbar”]

|a(*“foo\nbar”)
|prints [“foo\n”, “bar”]

[“foo\nbar”]

|a(*(1…4))
|prints [1, 2, 3, 4]

[1…4]

| *a = “foo\nbar”
| a gets [“foo\nbar”]

[“foo\nbar”]

| *a = (1…4)
| a gets [1…4]

[1…4]

| *a = “foo\nbar”, (1…3)
| a gets [“foo\nbar”, 1…3]

[“foo\nbar”, 1…3]

						matz.

Hi –

On Mon, 18 Sep 2006, Yukihiro M. wrote:

|in 1.9?

This may be an issue.

I’ve always thought it was convenient to have [*x] do the expanding
on x (including strings and ranges). But if it’s going to disappear,
I think it should disappear consistently, so that * doesn’t start
having a totally different meaning depending on the operand’s class.

David

On 9/18/06, Yukihiro M. [email protected] wrote:

|[*“foo\nbar”] #=> [“foo\nbar”]
|in 1.9?

Yes. And if you are curious you can try it by yourself.

Is 1.9.0 good enough?, because I get

ruby1.9 -ve ‘p [*“foo\nbar”]’
–>ruby 1.9.0 (2006-04-21) [i486-linux]
–>[“foo\n”, “bar”]

:frowning:

Robert

                                                    matz.


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

On 9/18/06, Rick DeNatale [email protected] wrote:

prints [1, 2, 3, 4]
Does the following happen only to me?

irb(main):001:0> def a(*arg)
irb(main):002:1> p arg
irb(main):003:1> end
=> nil
irb(main):004:0> a((1…3))
[1…3]
=> nil

Using ruby 1.8.4 (2006-04-14) [i386-mswin32].

Thanks,
Alvim.

On 9/18/06, [email protected] [email protected] wrote:

|which in 1.8.x produces [1, 2, 3, 4]
having a totally different meaning depending on the operand’s class.
I have found, and it seems it was not a common concern, that Range and
<=>
and #succ
are too closly coupled, but that is OT,

I think it would be a nice opportunity to define the protocol for *,
cleanly
and giving the community the opportunity to express the fors and
againsts
about potential implementations, well the good ol’ ML stuff :wink:

Personally I thought the #to_a protocol is perfect, but #to_a is not.

Cheers
Robert

David


David A. Black | [email protected]
Author of “Ruby for Rails” [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB’s Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

We could always have a “hyper-fatsplat” >>*<< [1]. Then it could do
everything at once, plus feed your cats when you go on vacation. :wink:

[1] see Perl6’s “hyper-fatarrow” -
http://www.nntp.perl.org/group/perl.perl6.language/25946

Regards,
Jordan

Marcelo A. wrote:

a((1…3))
=> nil

Using ruby 1.8.4 (2006-04-14) [i386-mswin32].

No, it the way it’s supposed to be.

a (1…3) #=> outputs: [1…3]
a *(1…3) #=> outputs: [1, 2, 3]

Cheers,
Daniel

On 9/18/06, MonkeeSage [email protected] wrote:

We could always have a “hyper-fatsplat” >>*<< [1]. Then it could do
everything at once, plus feed your cats when you go on vacation. :wink:

Noo, noo, Matz please do not listen to him, I have two dogs.
Make it feed dogs, PLEASE

Robert

[1] see Perl6’s “hyper-fatarrow” -

Re: Pair of lists => list of pairs? - nntp.perl.org

Regards,
Jordan


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

Yukihiro M. wrote:

When we talk about 1.9, the date matters. And we encourage to try the
most recent version from CVS HEAD. It’s 2006-09-18 today.

  					matz.

So does this mean that Why’s excellent talk at RailsConf Europe is
already out of date?

Hi,

In message “Re: Splat, #to_ary and #to_a
on Mon, 18 Sep 2006 17:54:32 +0900, “Robert D.”
[email protected] writes:

|Is 1.9.0 good enough?, because I get
|>
|ruby1.9 -ve ‘p [*“foo\nbar”]’
|–>ruby 1.9.0 (2006-04-21) [i486-linux]

When we talk about 1.9, the date matters. And we encourage to try the
most recent version from CVS HEAD. It’s 2006-09-18 today.

						matz.

unknown wrote:

Hi –

On Mon, 18 Sep 2006, Yukihiro M. wrote:

|in 1.9?

This may be an issue.

I’ve always thought it was convenient to have [*x] do the expanding
on x (including strings and ranges). But if it’s going to disappear,
I think it should disappear consistently, so that * doesn’t start
having a totally different meaning depending on the operand’s class.

I dunno–you have to use Range#to_a explicitly elsewhere so I
feel that would be consistent here also. I think my preferred
solution would be for splat to use #to_ary and leave everything
else explicit.

Of course this is a very limited application of the splat operator.

David

Hi,

In message “Re: Splat, #to_ary and #to_a
on Tue, 19 Sep 2006 01:36:22 +0900, “J2M” [email protected]
writes:

|> When we talk about 1.9, the date matters. And we encourage to try the
|> most recent version from CVS HEAD. It’s 2006-09-18 today.

|So does this mean that Why’s excellent talk at RailsConf Europe is
|already out of date?

I don’t know. I haven’t had a luck to hear his “excellent talk” yet.
Could anybody elaborate?

						matz.

Hi –

On Tue, 19 Sep 2006, Eero S. wrote:

on x (including strings and ranges). But if it’s going to disappear,
I think it should disappear consistently, so that * doesn’t start
having a totally different meaning depending on the operand’s class.

I dunno–you have to use Range#to_a explicitly elsewhere so I
feel that would be consistent here also.

My point is that I don’t want to have to use Range#to_a explicitly but
not String#to_a, nor the other way around. In other words, I don’t
want *(0…10) to do one thing and *“a\nb” to do another. It’s not
that I’m hung up on consistency per se (lots of cool Ruby things come
from inconsistency :slight_smile: but I don’t like things where there are two
cases and no clear reason why, so you have to memorize them
individually.

David

On 9/18/06, Yukihiro M. [email protected] wrote:

|–>ruby 1.9.0 (2006-04-21) [i486-linux]

When we talk about 1.9, the date matters. And we encourage to try the
most recent version from CVS HEAD. It’s 2006-09-18 today.

                                                    matz.

Heading right for it :slight_smile:
Thx
Robert


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein