2014-06-10 2 views
1

Я понимаю, что могу передать метод inject. Например,Почему некоторые методы работают с инъекцией, а некоторые - нет?

[1,2,3].inject(:+)  #=> 6 

но это один бросает

["1","2","3"].inject(:to_i) #=> TypeError: no implicit conversion of String into Integer 
["1","2","3"].inject(:to_s) #=> ArgumentError: wrong number of arguments (1 for 0) 

Я не делаю ничего конкретного, просто пытается получить мои основы права.

+1

В большинстве ситуаций в реальном мире вам нужно «map» вместо «inject», например. '[" 1 "," 2 "," 3 "]. Map (&: to_i) # => [1,2,3]'. –

+0

Правда. Это был начальный шаг, прежде чем я захотел выполнить сумму, то есть преобразовать в 'to_i' и использовать' inject' для ее суммирования. – Bala

+0

Я бы сделал оба шага в одно и то же время: '['1', '2', '3']. Reduce (0) {| sum, n | sum + n.to_i} '(обратите внимание, что' reduce' является псевдонимом для 'inject') –

ответ

5

Краткое объяснение - «обратный вызов для inject должен принимать два аргумента». Но это, вероятно, полностью не очистит его.

ОК, так что давайте посмотрим на обычный блок формы Inject:

[1, 2, 3].inject {|memo, number| memo + number} 

Передача символа работает таким же образом - он просто превращает символ в процедурный, который занимает место блока. При включении символа в процедурный, преобразование выглядит следующим образом:

class Symbol 
    def to_proc 
    proc {|receiver, *args| receiver.send(self, *args) } 
    end 
end 

Итак, когда вы проходите :+, он вызывает метод + значения памятки с текущим номером в качестве аргумента, так же, как 1 + 2.

Итак, когда вы проходите :to_i, это эквивалентно следующему:

["1", "2", "3"].inject {|memo, number_string| memo.to_i(number_string) } 

Но это не имеет никакого смысла. Вы пытаетесь передать строку в качестве аргумента в to_i. который недействителен.

+2

Хороший ответ. Небольшая деталь, которая может быть интересна кому-то: в предпоследней строке Чака, потому что 'inject' не дается аргумент,« memo »изначально назначается первый элемент массива (' '1" '), поэтому возникает исключение когда Ruby встречает «1» .to_i («2») '. –

+0

@CarySwoveland одобрил ваш комментарий для использования «предпоследнего» :) –

+0

Спасибо, @Mark, я использую этот термин при каждой возможности. Иногда это просто повод для комментария. Возможно, я должен был бы вместо этого упомянуть о упоминании Чака об «эквиваленте» в его антепенутической линии. –

Смежные вопросы