Undocumented behaviour of Array#join

Guys,

Have you ever seen this ?

2.1.2 :001 > [2,[3,4],1,8,[[[5]]]].join
=> "234185"
2.1.2 :002 > [2,[3,4],1,8,[[[5]]]].join("|")
=> "2|3|4|1|8|5"
2.1.2 :003 >

Regards,
Arup Rakshit

Wow

I tried this just for check and behaves the same

[2,[3,4],1,8,[[[5]]]] * '|'
=> "2|3|4|1|8|5"

···

2014-08-05 8:15 GMT-03:00 Arup Rakshit <aruprakshit@rocketmail.com>:

Guys,

Have you ever seen this ?

2.1.2 :001 > [2,[3,4],1,8,[[[5]]]].join
=> "234185"
2.1.2 :002 > [2,[3,4],1,8,[[[5]]]].join("|")
=> "2|3|4|1|8|5"
2.1.2 :003 >

Regards,
Arup Rakshit

--
Juanjo Conti
blog: http://www.juanjoconti.com.ar

Seems like it joins the array recursively. Source:

As #join returns a String, I'm sort of wondering what else you were
expecting it to do?

···

On Tue, Aug 5, 2014 at 6:15 AM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

Have you ever seen this ?

2.1.2 :001 > [2,[3,4],1,8,[[[5]]]].join
=> "234185"
2.1.2 :002 > [2,[3,4],1,8,[[[5]]]].join("|")
=> "2|3|4|1|8|5"
2.1.2 :003 >

I think he expected a failure.

···

2014-08-05 19:15 GMT-03:00 tamouse pontiki <tamouse.lists@gmail.com>:

On Tue, Aug 5, 2014 at 6:15 AM, Arup Rakshit <aruprakshit@rocketmail.com> > wrote:

Have you ever seen this ?

2.1.2 :001 > [2,[3,4],1,8,[[[5]]]].join
=> "234185"
2.1.2 :002 > [2,[3,4],1,8,[[[5]]]].join("|")
=> "2|3|4|1|8|5"
2.1.2 :003 >

As #join returns a String, I'm sort of wondering what else you were
expecting it to do?

--
Juanjo Conti
blog: http://www.juanjoconti.com.ar

This has been standard behaviour since at least 1.8.7

True, it's not well documented.​

···

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

Another possible expectation could be that it works like this:

  class Array
    def join sep=$,
      reduce do |s,e|
        s.to_s + sep.to_s + e.to_s
      end.to_s
    end
  end

(Apologies for suboptimal to_s, but you get the idea). Which, depending on
Array#to_s, could do the following:

  [1,[2,3]].join '|'
   #=> "1|[2, 3]" in 1.9+, or
   # "1|23" in 1.8

Note that the following already happens:

  [1,{2=>3}].join '|'
   #=> "1|{2=>3}" in 1.9+, or
   #=> "1|23" in 1.8

And it doesn't matter if you define Hash#join, the recursion only happens
if the object is_a? Array.

So, again, the documentation is lacking.

···

On 6 August 2014 08:20, Juanjo Conti <jjconti@gmail.com> wrote:

I think he expected a failure.

2014-08-05 19:15 GMT-03:00 tamouse pontiki <tamouse.lists@gmail.com>:

On Tue, Aug 5, 2014 at 6:15 AM, Arup Rakshit <aruprakshit@rocketmail.com> >> wrote:

Have you ever seen this ?

2.1.2 :001 > [2,[3,4],1,8,[[[5]]]].join
=> "234185"
2.1.2 :002 > [2,[3,4],1,8,[[[5]]]].join("|")
=> "2|3|4|1|8|5"
2.1.2 :003 >

As #join returns a String, I'm sort of wondering what else you were
expecting it to do?

--
Juanjo Conti
blog: http://www.juanjoconti.com.ar

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

Another possible expectation could be that it works like this:

  class Array
    def join sep=$,
      reduce do |s,e|
        s.to_s + sep.to_s + e.to_s
      end.to_s
    end
  end

Or, probably a tad more efficient

class Array
  def join2(sep = $,)
    sep = sep.to_s

    reduce nil do |s,e|
      if s
        s << sep << e.to_s
      else
        e.to_s
      end
    end
  end
end

Another way to achieve that would be

irb(main):003:0> [2,[3,4],1,8,[[[5]]]].map(&:to_s).join("|")
=> "2|[3, 4]|1|8|[[[5]]]"

(Apologies for suboptimal to_s, but you get the idea). Which, depending on
Array#to_s, could do the following:

  [1,[2,3]].join '|'
   #=> "1|[2, 3]" in 1.9+, or
   # "1|23" in 1.8

Note that the following already happens:

  [1,{2=>3}].join '|'
   #=> "1|{2=>3}" in 1.9+, or
   #=> "1|23" in 1.8

And it doesn't matter if you define Hash#join, the recursion only happens if
the object is_a? Array.

So, again, the documentation is lacking.

I agree.

Kind regards

robert

···

On Wed, Aug 6, 2014 at 12:52 AM, Matthew Kerwin <matthew@kerwin.net.au> wrote:

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/