Private method `split'?


#1

Somehow, when trying to split an element in an array, split is no
longer working.

I get this error:

private method `split’ called for #Array:0xa7ad1ba4 (NoMethodError)

I can’t show the code which generates the array, but I can reproduce
the error with something simple like this:

puts [“a\nb”, “c”].split("\n")

However, imagine if you would that code like this could generate the
same private method error.

array = [“a\nb”, “c”]
puts array[0].split("\n")

(where ‘array[0]’ is an element in a slightly complex array)

Why can’t I use split with an element in my array? What’s going on
here?

I can do { puts array[0].inspect } and everything is normal…

My goal is to convert an array which has strings of varying sizes (one
or more lines) into an array where each element has just one line of
text. Maybe there’s a better way to do this and I can avoid this
wierdness?


#2

On Jun 3, 2006, at 9:07 PM, Sy Ali wrote:

puts [“a\nb”, “c”].split("\n")
Why can’t I use split with an element in my array? What’s going on
here?

I can do { puts array[0].inspect } and everything is normal…

My goal is to convert an array which has strings of varying sizes (one
or more lines) into an array where each element has just one line of
text. Maybe there’s a better way to do this and I can avoid this
wierdness?

array = [ “one line\n”, “two line\nred line\n”, “blue line” ]
array.map { |elem| elem.to_a }.flatten
#=> [“one line\n”, “two line\n”, “red line\n”, “blue line”]


#3

On 6/3/06, Logan C. removed_email_address@domain.invalid wrote:

array = [ “one line\n”, “two line\nred line\n”, “blue line” ]
array.map { |elem| elem.to_a }.flatten
#=> [“one line\n”, “two line\n”, “red line\n”, “blue line”]

Curious. That’s not working as I’d expect. My misbehaving array
element still has \n in the middle of it.


#4

On 6/3/06, Mike S. removed_email_address@domain.invalid wrote:

Without more concrete information it is hard to guess at what is
really going on!

I’m not sure how to better describe things. This issue came up when I
began to carve up my code into chunks which pass information back and
forth.

I assume I’ve run into some issue where the array which is being
generated in one place is somehow becoming alien to code that’s trying
to use it elsewhere else.

I just don’t know how to decipher the error message, nor do I
understand how I can get, use and inspect the array but (only) split
won’t work on it the way I expect.

Your example code went over my head… but something in there seems
familiar. I’m going to renovate my code and see what I can come up
with.


#5

On 3-Jun-06, at 10:25 PM, Sy Ali wrote:

On 6/3/06, Logan C. removed_email_address@domain.invalid wrote:

array = [ “one line\n”, “two line\nred line\n”, “blue line” ]
array.map { |elem| elem.to_a }.flatten
#=> [“one line\n”, “two line\n”, “red line\n”, “blue line”]

Curious. That’s not working as I’d expect. My misbehaving array
element still has \n in the middle of it.

Is the misbehaving array element really a string, and what exactly
are you doing in your code. In your earlier post you said:

Why can’t I use split with an element in my array? What’s going on
here?

I can do { puts array[0].inspect } and everything is normal…

but inspect turns things into strings. for example I can imagine
code like this:

ratdog:~ mike$ irb
irb(main):001:0> class Foo
irb(main):002:1> def initialize(s) ; @s = s ; end
irb(main):003:1> def inspect ; @s ; end
irb(main):004:1> end
=> nil
irb(main):005:0> array = [Foo.new(“one\ntwo\n”)]
=> [one
two
]
irb(main):006:0> array[0].inspect
=> “one\ntwo\n”
irb(main):007:0> array[0].split("\n")
NoMethodError: private method `split’ called for one
two
:Foo
from (irb):7
from :0

Without more concrete information it is hard to guess at what is
really going on!

Mike

Mike S. removed_email_address@domain.invalid
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.


#6

On 6/4/06, Sy Ali removed_email_address@domain.invalid wrote:

I don’t get it… but at least it’s working. Now i’m on to other
curious issues, such as why
pause = gets.chomp
gives me:
`lstat’: No such file or directory - pause (Errno::ENOENT)
and works differently inside and outside of a wrapper-script. Hrmph!

Well… it’s also crap like this:

`gets’: Is a directory - directory (Errno::EISDIR)

Somehow, unreleated code is interfering. I’ll figure it out.


#7

Ok, so here’s a simplified summary:

def a(array)

build an array in here

return array # This is the problem!
end

foo.each { |i|
output << a(i)
}
puts output.join("\n")

In one place I was building an array internally and then returning
that array. It was then being used to build another array. The
problem is in the return statement.

So
return array
becomes
return array.join("\n")

I don’t get it… but at least it’s working. Now i’m on to other
curious issues, such as why
pause = gets.chomp
gives me:
`lstat’: No such file or directory - pause (Errno::ENOENT)
and works differently inside and outside of a wrapper-script. Hrmph!


#8

On 6/4/06, Sy Ali removed_email_address@domain.invalid wrote:

Well… it’s also crap like this:

`gets’: Is a directory - directory (Errno::EISDIR)

Somehow, unreleated code is interfering. I’ll figure it out.

Pardon the mailing list blogging… I do understand what’s been going
on. My “pause” routine takes advantage of something which I shouldn’t
be doing.

instead of
pause = gets
do
ARGV.clear
ARGV << gets

=)

Ok, all problems are solved… now I can svn commit and go to sleep. =)


#9

On 6/4/06, Robert K. removed_email_address@domain.invalid wrote:

Your problem here is that you call Kernel.split which is private

I think I understand. I’m not entirely sure why the same block of
code will use split in one way verses another way (kernel vs string)
depending entirely upon the array that its working on… but things
have worked out in the end.

Solutions have been suggested already. Here’s another one that avoids
the use of flatten because that is less efficient:

Thank you… that obsoleted a wierd block of code I whipped up.


#10

Explaining the error you saw:

2006/6/4, Sy Ali removed_email_address@domain.invalid:

puts [“a\nb”, “c”].split("\n")
Your problem here is that you call Kernel.split which is private
because it’s intended to be used like this:

irb(main):009:0> $_=“foo\nbar”; split /\n/
=> [“foo”, “bar”]

You can find that out like this:

irb(main):001:0> [].method :split
=> #<Method: Array(Kernel)#split>

This is typically used in command line one liners

ruby -n -e ‘puts split(/foo/)’ some_file

However, imagine if you would that code like this could generate the
same private method error.

array = [“a\nb”, “c”]
puts array[0].split("\n")

(where ‘array[0]’ is an element in a slightly complex array)

No, because now you are calling String#split which is actually public.

irb(main):011:0> “foo\nbar”.split /\n/
=> [“foo”, “bar”]

Here you can see that it’s a different method:

irb(main):002:0> “”.method :split
=> #<Method: String#split>

Why can’t I use split with an element in my array? What’s going on here?

I can do { puts array[0].inspect } and everything is normal…

My goal is to convert an array which has strings of varying sizes (one
or more lines) into an array where each element has just one line of
text. Maybe there’s a better way to do this and I can avoid this
wierdness?

Solutions have been suggested already. Here’s another one that avoids
the use of flatten because that is less efficient:

irb(main):013:0> [“foo\nbar”, “buz”, “bat\ndos”].inject([]){|ar,s|
ar.concat(s.split(/\n/))}
=> [“foo”, “bar”, “buz”, “bat”, “dos”]

Kind regards

robert


#11

2006/6/4, Sy Ali removed_email_address@domain.invalid:

On 6/4/06, Robert K. removed_email_address@domain.invalid wrote:

Your problem here is that you call Kernel.split which is private

I think I understand. I’m not entirely sure why the same block of
code will use split in one way verses another way (kernel vs string)
depending entirely upon the array that its working on… but things
have worked out in the end.

You’re seeing basic object orientation at work here: a method is
always invoked on an object and it depends on the type of the object
which behavior is exposed. The only special thing about Kernel.split
is that it’s usually invoked without an explicit receiver, which means
“self” is the receiver. That’s why I presented the example calls from
my IRB session that show what class the different methods were defined
on. I don’t know your background so it’s probably a bit difficult to
grasp in the beginning. But then again, Ruby is one of the better
languages to learn OO with because it minimizes on the number of
exceptions: in Ruby everything is an object and there is no
distinction between POD’s and objects like in Java for example.

Solutions have been suggested already. Here’s another one that avoids
the use of flatten because that is less efficient:

Thank you… that obsoleted a wierd block of code I whipped up.

#inject frequently does. :-))

Kind regards

robert