Ruby: закрытый метод для 3:Fixnum

Я пытаюсь узнать нюансы этой простой функции, но не уверен, что мне нужно сделать, чтобы исправить эту ошибку NoMethodError. Как сделать разделение публичным, а не частным? Это решит проблему?

Вот мой код:

DATA = [3, 4, 5, 6, 7, 8]
DATA.each do |line|
vals = line.split
print vals[0] + vals[1], " "
end

Вот сообщение об ошибке, которое я получаю при запуске в IRB:

NoMethodError: private method `split' called for 3:Fixnum

3 ответа

Решение

Вы вызываете метод split на числовом объекте - этот метод существует в String класс, но не в Fixnum,

Я думаю, что вы пытаетесь сделать это:

DATA = ['3,4', '5,6', '7,8']
DATA.each do |val|
  vals = line.split ','
  print vals[0] + vals[1], " "
end

Непонятно, что вы пытаетесь сделать. У вас нет "строки", у вас есть элемент из массива, который является целочисленным значением. Split это метод, определенный на String.

DATA = [3, 4, 5, 6, 7, 8]
DATA.each do |val|
  print val
end

Теперь причина, по которой вы получаете это запутанное сообщение об ошибке, немного интересна. Как это бывает, есть Kernel#split что позволяет использовать Perl-подобную краткость для сценариев. Разбивает глобальную переменную $_ который содержит последний результат из gets,

>> gets
how now brown cow
=> "how now brown cow\n"
>> split ' '
=> ["how", "now", "brown", "cow"]
>> puts $_
how now brown cow

Но смешивание с Object, чтобы оно было доступно на уровне сценария, оставляет проблему в том, что каждый созданный класс в конечном итоге имеет #split метод.

Если вы запустите простой старый split(), каждый объект в системе будет реагировать, но, к счастью, только с ошибкой.

Делая его закрытым методом, он доступен на верхнем уровне для сценариев (потому что "Объект" открыт или что-то в этом роде), но не является частью API каждого экземпляра объекта.

Угадай, что ты действительно хочешь:

DATA = 3..8
DATA.each_cons(2) do |a,b|
  puts "#{a} + #{b} = #{a+b}"
end
#=> 3 + 4 = 7
#=> 4 + 5 = 9
#=> 5 + 6 = 11
#=> 6 + 7 = 13
#=> 7 + 8 = 15

Изменить: исходя из желания оперировать последовательными парами:

DATA = 3..8    # or DATA = [3,4,5,6,7,8]
DATA.each_slice(2) do |a,b|
  puts "#{a} + #{b} = #{a+b}"
end
#=> 3 + 4 = 7
#=> 5 + 6 = 11
#=> 7 + 8 = 15
Другие вопросы по тегам